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

Why is a UTF-8 string not equal to the equivalent ASCII-8BIT string in Ruby 2.0?

我正在使用 Ruby 2.3:

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

我在一个包含它的文件上做了一个File.binread(),所以这个字符串的编码是ASCII-8BIT。但是,在我的代码中,我通过将它与文字字符串 "\xFF\xFE"(默认情况下所有 Ruby 字符串的编码为 UTF-8 进行比较来检查是否确实读取了该字符串。

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

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

(1) why does it return false?

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

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

a = 'E'.encode('ISO8859-1')  #=> "E"
b = 'E'.encode('ISO8859-15') #=> "E"

a.bytes #=> [69]
b.bytes #=> [69]
a == b  #=> true

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

a = 'É'.encode('ISO8859-1')  #=> "\xC9"
b = 'É'.encode('ISO8859-15') #=> "\xC9"

a.bytes #=> [201]
b.bytes #=> [201]
a == b  #=> false

您的字符串无法用 US-ASCII 表示,因为它的两个字节都在其范围之外:

"\xFF\xFE".bytes #=> [255, 254]

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

"\xFF\xFE".encode('US-ASCII', 'ASCII-8BIT', :undef => :replace)
#=> "??"

因此,当与另一种编码的字符串进行比较时,该字符串将 return false,无论其内容如何。

(2) what is the best way to go about achieving what i want?

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

IO.binread('your_file', 2) == "\xFF\xFE".b

或者你可以比较它的 bytes:

IO.binread('your_file', 2).bytes == [0xFF, 0xFE]