为什么 UTF-8 字符串不等于 Ruby 2.0 中等效的 ASCII-8BIT 字符串?

hor*_*guy 3 ruby string encoding utf-8 ruby-2.0

我使用的是 Ruby 2.3:

我有以下字符串:"\xFF\xFE"

我对File.binread()包含它的文件执行了 a 操作,因此该字符串的编码是ASCII-8BIT. "\xFF\xFE"然而,在我的代码中,我通过将其与文字字符串(其默认编码UTF-8与所有 Ruby 字符串相同)进行比较来检查该字符串是否确实被读取。

然而,即使两个字符串包含相同的字节,比较也会返回false- 恰好一个是编码的ASCII-8BIT,另一个是编码的UTF-8

我有两个问题:(1)为什么它会返回false?(2) 实现我想要的目标的最佳方法是什么?我只是想检查我读取的字符串是否匹配"\xFF\xFE"

Ste*_*fan 5

\n

(1) 为什么会返回false

\n
\n\n

比较字符串时,它们必须采用相同的编码,或者它们的字符必须可以用 US-ASCII 进行编码。

\n\n

如果字符串仅包含字节值 0 到 127,则比较按预期进行:( 0b0xxxxxxx)

\n\n
a = \'E\'.encode(\'ISO8859-1\')  #=> "E"\nb = \'E\'.encode(\'ISO8859-15\') #=> "E"\n\na.bytes #=> [69]\nb.bytes #=> [69]\na == b  #=> true\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果它包含任何字节值 128 到 255,则失败:( 0b1xxxxxxx)

\n\n
a = \'\xc3\x89\'.encode(\'ISO8859-1\')  #=> "\\xC9"\nb = \'\xc3\x89\'.encode(\'ISO8859-15\') #=> "\\xC9"\n\na.bytes #=> [201]\nb.bytes #=> [201]\na == b  #=> false\n
Run Code Online (Sandbox Code Playgroud)\n\n

您的字符串无法以 US-ASCII 表示,因为它的两个字节都超出了其范围:

\n\n
"\\xFF\\xFE".bytes #=> [255, 254]\n
Run Code Online (Sandbox Code Playgroud)\n\n

尝试转换它不会产生任何有意义的结果:

\n\n
"\\xFF\\xFE".encode(\'US-ASCII\', \'ASCII-8BIT\', :undef => :replace)\n#=> "??"\n
Run Code Online (Sandbox Code Playgroud)\n\n

false因此,当与其他编码中的字符串进行比较时,无论其内容如何,​​该字符串都会返回。

\n\n
\n

(2) 实现我想要的目标的最佳方法是什么?

\n
\n\n

您可以将您的字符串与具有相同编码的字符串进行比较。binread返回编码中的字符串ASCII-8BIT,因此您可以使用b它来创建兼容的字符串:

\n\n
IO.binread(\'your_file\', 2) == "\\xFF\\xFE".b\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者你可以比较它bytes

\n\n
IO.binread(\'your_file\', 2).bytes == [0xFF, 0xFE]\n
Run Code Online (Sandbox Code Playgroud)\n

  • 不存在“8位ascii”这样的东西。ASCII 过去、现在、将来都是 7 位。 (3认同)