2017-10-18 112 views
1

我使用Ruby 2.3:爲什麼UTF-8字符串不等於Ruby 2.0中相應的ASCII-8BIT字符串?

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

我就包含它的文件做一個File.binread(),所以這個字符串的編碼是ASCII-8BIT。但是,在我的代碼中,我通過將字符串與"\xFF\xFE"(因爲所有的Ruby字符串默認情況下編碼爲UTF-8)進行比較來檢查該字符串是否確實被讀取。

然而,比較返回false,即使兩個字符串包含相同的字節 - 它只是碰巧,一個是與編碼ASCII-8BIT,另一個是UTF-8

我有兩個問題:(1)爲什麼它的回報false? (2)什麼是實現我想要的最好方法?我只想檢查我讀的字符串是否匹配"\xFF\xFE"

+0

如果你只是想讀取一個Unicode文件BOM,您可以傳遞BOM的UTF-8的[encoding](http://ruby-doc.org/core-2.4.2/IO.html#method-c-new-label-IO+Encoding) 「讓Ruby自動處理它。 – Stefan

回答

4

(1)爲什麼它返回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) 
#=> "??" 

字符串因此將返回false被比較,以另一種編碼的字符串時,無論其內容。

(2)什麼是最好的方式去實現我想要的?

您可以將您的字符串與具有相同編碼的字符串進行比較。 binread返回一個字符串在ASCII-8BIT編碼,因此您可以使用b來創建一個兼容的一個:

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

,或者你可以比較其bytes

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

但它的8位ascii和字符255和254被定義。那麼,那是怎麼回事? ' 「\ XFF \ xFE如果」。編碼('ASCII-8BIT')'工作得很好。是否因爲它不是有效的UTF-8? – horseyguy

+3

沒有「8位ascii」這樣的東西。 ASCII一直是,並且一直是7位。 –

+0

@banister你把'ASCII-8BIT'和'US-ASCII'混淆了,我的回答在這方面也不是很精確。我已經相應地更新了它。 – Stefan

相關問題