为什么 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]
我正在使用 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]