提问人:il mietitore 提问时间:3/22/2022 最后编辑:il mietitore 更新时间:4/7/2022 访问量:244
无法让 Ruby 接受 UTF-8 输入
Can't get Ruby to accept UTF-8 input
问:
自从几个版本的 Ruby 以来,我就遇到了这个问题,同时我什至改变了计算机和操作系统。尽管如此,我根本无法通过它。关键是,现在我正在使用 Ruby 为我的专业流媒体服务制作图形叠加层,所以我真的需要一劳永逸地完成这项工作。
让我们把这个线程看作是对我 1 年零 8 个月前发布的这个旧问题的巨大更新,该问题与当时的 Ruby 版本有关。现在我正在开发 Windows 10,Ruby 的版本为 3.1.1。
下面是一个 MWE:
puts "Write something with accents such as àòèùì, or €"
asd = gets
puts asd
如果我键入任何重音字母,会发生什么情况:
如果我输入“€”,会发生什么情况:
在我上面提到的旧线程中,我使用了两个不再需要的命令。但是,为了论证,让我们尝试一下:
`chcp 65001`
puts "Write something with accents such as àòèùì, or €"
asd = gets
puts asd
chcp 65001
应将终端的编码切换为 UTF-8。截至 2022 年,这应该是默认值。不过,如果我使用那句话,确实会有所改变......更糟糕的是。
如果我输入任何重音字母,我必须在键入字符后按两次回车键。我会得到两个破碎的字形,而不是一个。
如果我输入“€”符号,程序将立即崩溃,甚至在我按下回车键之前。
添加实际上对 MWE 没有任何影响,无论是否使用命令。# encode: utf-8
chcp 65001
这里的问题是,这件小事对我编写的任何其他程序都有深远的影响,在这些程序中,我必须考虑可能包含重音字母的用户输入。
例如,如果我尝试通过 获取用户输入,会发生什么。tty-prompt
require "tty-prompt"
prompt = TTY::Prompt.new
asd = prompt.ask("Write something with accents such as àòèùì, or €")
puts asd
重音字母在插入时显示为损坏的字形,然后在我按回车键后消失而不是显示:
像往常一样,“€”符号只是显示为问号:
这个问题扩展到我甚至没有输入的字符。例如,Ruby 无法正确显示 gem 使用的字符。这里:tty-spinner
require "tty-spinner"
spinner = TTY::Spinner.new("[:spinner] Loading ...", format: :pulse_2)
spinner.auto_spin
sleep(2)
spinner.stop("Done!")
如您所见,它在执行时不会显示字符:
最后,它实际上能够读取写在 UTF-8 编码文本文件上的重音字母,并且它应该能够生成一个 UTF-8 编码的 HTML 文件,但我正在使用 OBS 访问该文件,它无法读取它,这让我怀疑该文件是否真的是用 UTF-8 编码的, 因为在这种情况下,OBS应该能够读取它。
这个程序...
def indent (indentazione, stringa)
unless indentazione == 0
for cont in 1..indentazione
stringa.prepend("\t")
end
end
return stringa
end
testo = File.open('C:\Users\rapto\OneDrive\Documenti\Macro streaming\MietTV\riquadro\riquadro_updater.txt', "r").readlines[0].chomp
pagina = File.open('C:\Users\rapto\OneDrive\Documenti\Macro streaming\MietTV\riquadro\riquadro.html', "w:UTF-8")
pagina.puts(indent(0, "<html>"))
pagina.puts(indent(0, ""))
pagina.puts(indent(0, "<head>"))
pagina.puts(indent(1, "<link rel=\"stylesheet\" href=\"../stile.css\">"))
pagina.puts(indent(0, "</head>"))
pagina.puts(indent(0, ""))
pagina.puts(indent(0, "<body>"))
pagina.puts(indent(1, "<div id=\"riquadro\">"))
pagina.puts(indent(2, "<p id=\"riquadro_testo\">" + testo + "</p>"))
pagina.puts(indent(1, "</div>"))
pagina.puts(indent(0, "</body>"))
pagina.puts(indent(0, ""))
pagina.puts(indent(0, "</html>"))
puts "Operazione completata"
...将读取此文本文件...
...由此 Bash 代码创建...
@ECHO OFF
chcp 65001
SET /P data1= "Inserisci il testo del riquadro: "
ECHO %data1%> "C:\Users\rapto\OneDrive\Documenti\Macro streaming\MietTV\riquadro\riquadro_updater.txt"
"C:\Users\rapto\OneDrive\Documenti\Macro streaming\MietTV\riquadro\riquadro_updater.rb"
...并生成此 HTML 页面...
<html>
<head>
<link rel="stylesheet" href="../stile.css">
</head>
<body>
<div id="riquadro">
<p id="riquadro_testo">La magia nera della narrazione: età dei personaggi</p>
</div>
</body>
</html>
...这将由 Opera 正确呈现......
...但不是 OBS,它应该能够读取 UTF-8 编码的页面。
幸运的是,我可以通过将所有重音字母转换为各自的 HTML 代码来解决后一个问题。不过,如果一切顺利就好了。
在我看来,Ruby 在管理 UTF-8 编码文件方面显然存在一些问题。这完全可能是我在如何处理它们方面遗漏了一些东西。可能是我设置不正确。欢迎所有建议。
更新
如@Holger所示,问题似乎主要是由默认的Windows 10终端引起的。我通过从Microsoft商店“Windows终端”下载其更新版本解决了这个问题。
如果我使用我通过所述终端提供的第一个 mwe,我可以毫不费力地有效地键入重音字母,并正确地将它们作为输出接收回来:
不过,它仍然不适用于欧元符号:
如果我包含该部分,该程序将出现与以前类似的问题。如果我输入一个重音字母,我需要按两次回车键,然后接收这两个符号作为输出:chcp 65001
如果我输入欧元符号,它会崩溃。
答:
这可能与大多数 Windows shell 本身不使用 UTF-8 编码有关。因此,如果外部程序(例如 Ruby 程序)从 shell 读取数据,它可能不是以 UTF-8 编码(正如 Ruby 所期望的那样),而是以其他编码编码,具体取决于您的系统。
然而,Ruby 没有办法真正知道数据的编码。你可能不得不告诉它。从 Ruby 3.0 开始,Ruby 默认采用 UTF-8 作为 Windows 上的外部编码(有关详细信息,请参见功能 #16604)。以前的版本使用 Windows 版本的“本机”编码,这可能会导致在将数据写入文件等时出现各种问题。
现在,在您的示例中发生的情况是 Ruby 使用 .shell 提供了一些数据,Ruby 由于其设置而假定这些数据是 UTF-8 格式,但事实并非如此。gets
Encoding.default_external
根据 shell 如何解释 Ruby 发送的数据,事情可能会出乎意料......
唯一实际的解决方案是确保你的 shell 在它们交换的数据的编码上与 Ruby 一致。为此,您可能需要调整 shell 的设置。
评论
chcp 65001
chcp 65001
评论
à
0xC3
0xA0
Ã
<meta charset='utf-8'>