无法让 Ruby 接受 UTF-8 输入

Can't get Ruby to accept UTF-8 input

提问人:il mietitore 提问时间:3/22/2022 最后编辑:il mietitore 更新时间:4/7/2022 访问量:244

问:

自从几个版本的 Ruby 以来,我就遇到了这个问题,同时我什至改变了计算机和操作系统。尽管如此,我根本无法通过它。关键是,现在我正在使用 Ruby 为我的专业流媒体服务制作图形叠加层,所以我真的需要一劳永逸地完成这项工作。

让我们把这个线程看作是对我 1 年零 8 个月前发布的这个旧问题的巨大更新,该问题与当时的 Ruby 版本有关。现在我正在开发 Windows 10,Ruby 的版本为 3.1.1。

下面是一个 MWE:

puts "Write something with accents such as àòèùì, or €"
asd = gets
puts asd

如果我键入任何重音字母,会发生什么情况:

error #1

如果我输入“€”,会发生什么情况:

error #2

在我上面提到的旧线程中,我使用了两个不再需要的命令。但是,为了论证,让我们尝试一下:

`chcp 65001`

puts "Write something with accents such as àòèùì, or €"
asd = gets
puts asd

chcp 65001应将终端的编码切换为 UTF-8。截至 2022 年,这应该是默认值。不过,如果我使用那句话,确实会有所改变......更糟糕的是。

error #3

如果我输入任何重音字母,我必须在键入字符后按两次回车键。我会得到两个破碎的字形,而不是一个。

如果我输入“€”符号,程序将立即崩溃,甚至在我按下回车键之前。

添加实际上对 MWE 没有任何影响,无论是否使用命令。# encode: utf-8chcp 65001

这里的问题是,这件小事对我编写的任何其他程序都有深远的影响,在这些程序中,我必须考虑可能包含重音字母的用户输入。

例如,如果我尝试通过 获取用户输入,会发生什么。tty-prompt

require "tty-prompt"

prompt = TTY::Prompt.new
asd = prompt.ask("Write something with accents such as àòèùì, or €")
puts asd

重音字母在插入时显示为损坏的字形,然后在我按回车键后消失而不是显示:

error 4.1 error 4.2

像往常一样,“€”符号只是显示为问号:

error 5

这个问题扩展到我甚至没有输入的字符。例如,Ruby 无法正确显示 gem 使用的字符。这里:tty-spinner

require "tty-spinner"

spinner = TTY::Spinner.new("[:spinner] Loading ...", format: :pulse_2)
spinner.auto_spin
sleep(2)
spinner.stop("Done!")

如您所见,它在执行时不会显示字符:

error #6.1 error #6.2

最后,它实际上能够读取写在 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"

...将读取此文本文件...

errore #7.1

...由此 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 正确呈现......

error #7.2

...但不是 OBS,它应该能够读取 UTF-8 编码的页面。

error #7.3

幸运的是,我可以通过将所有重音字母转换为各自的 HTML 代码来解决后一个问题。不过,如果一切顺利就好了。

在我看来,Ruby 在管理 UTF-8 编码文件方面显然存在一些问题。这完全可能是我在如何处理它们方面遗漏了一些东西。可能是我设置不正确。欢迎所有建议。

更新

如@Holger所示,问题似乎主要是由默认的Windows 10终端引起的。我通过从Microsoft商店“Windows终端”下载其更新版本解决了这个问题。

如果我使用我通过所述终端提供的第一个 mwe,我可以毫不费力地有效地键入重音字母,并正确地将它们作为输出接收回来:

round 2, #1

不过,它仍然不适用于欧元符号:

round 2, #2

如果我包含该部分,该程序将出现与以前类似的问题。如果我输入一个重音字母,我需要按两次回车键,然后接收这两个符号作为输出:chcp 65001

round 2, #3

如果我输入欧元符号,它会崩溃。

Ruby 编码 UTF-8

评论

0赞 Yakov 3/22/2022
也许这只是一个 Windows 终端问题。我尝试了第一个示例,它适用于我的 Linux 机器。
0赞 matt 3/23/2022
在 OBS 问题中,OBS 将 HTML 解释为 CP1252 或 ISO-8859-1(也可能是其他 8859 编码之一)。编码为 UTF-8 的字符是两个字节和 。这些被解释为 ISO-8859-1 的字节是字符和不间断空格,这就是 OBS 屏幕截图中的内容。我不知道OBS,你能在某处指定页面编码吗?否则,也许添加一个标签?à0xC30xA0Ã<meta charset='utf-8'>

答:

0赞 Holger Just 3/22/2022 #1

这可能与大多数 Windows shell 本身不使用 UTF-8 编码有关。因此,如果外部程序(例如 Ruby 程序)从 shell 读取数据,它可能不是以 UTF-8 编码(正如 Ruby 所期望的那样),而是以其他编码编码,具体取决于您的系统。

然而,Ruby 没有办法真正知道数据的编码。你可能不得不告诉它。从 Ruby 3.0 开始,Ruby 默认采用 UTF-8 作为 Windows 上的外部编码(有关详细信息,请参见功能 #16604)。以前的版本使用 Windows 版本的“本机”编码,这可能会导致在将数据写入文件等时出现各种问题。

现在,在您的示例中发生的情况是 Ruby 使用 .shell 提供了一些数据,Ruby 由于其设置而假定这些数据是 UTF-8 格式,但事实并非如此。getsEncoding.default_external

根据 shell 如何解释 Ruby 发送的数据,事情可能会出乎意料......

唯一实际的解决方案是确保你的 shell 在它们交换的数据的编码上与 Ruby 一致。为此,您可能需要调整 shell 的设置。

评论

0赞 il mietitore 3/23/2022
但是 shell 不应该通过命令切换到 UTF-8 吗?另外,为什么这甚至适用于微调器示例,其中 shell 根本没有给出输入?chcp 65001
0赞 Holger Just 3/23/2022
引用 ruby 语言跟踪器上的链接问题:“65001 的 Windows 实现在控制台中存在错误。我最近没有验证它,但几年前就不可靠了。至于微调器输出,默认情况下 Ruby 也会在输出中生成 UTF-8。如果你的外壳期望不同的东西,事情就会再次破裂。chcp 65001