2011-06-16 20 views
1

我正在寫一個Ruby腳本來處理一個大的文本文件,並不斷得到一個奇怪的編碼錯誤。 這裏的情況:爲什麼在讀取文本文件時出現「UTF-8中的無效字節序列」錯誤?

input_data = File.new(in_path, 'r').read 
p input_data.encoding.name # UTF-8 
break_char = "\r".encode("UTF-8") 
p break_char # "\r" 
p break_char.encoding.name # "UTF-8" 
input_data.split(",".encode("UTF-8")) 
p Encoding.compatible?(input_data, break_char) # # Encoding:UTF-8> 

這會產生錯誤:in 'split': invalid byte sequence in UTF-8 (ArgumentError)

我看http://blog.grayproductions.net/articles/ruby_19s_string,看着其他的解決方案,顯然同樣的問題,但仍然不能工作了,爲什麼它的發生的時候,我相信我控制編碼。

我在OSX使用Ruby 1.9.2

回答

8

顯然你的輸入文件不是UTF-8(或者至少不是全部)。如果你不關心非ascii字符,你可以簡單地假設你的文件是ascii-8bit編碼的。順便說一句,您的分隔符(break_char)不會引起問題,因爲逗號在UTF-8中的編碼方式與在ASCII中的編碼方式相同。

fname = 'test.in' 

# create example file and fill it with invalid UTF-8 sequence 
File.open(fname, 'w') do |f| 
    f.write "\xc3\x28" 
end 

# then try to read and parse it 
s = File.open(fname) do |f| # file opened as UTF-8 
#s = File.open(fname, 'r:ascii-8bit') do |f| # file opened as ascii-8bit 
    f.read 
end 
p s.split ',' 
+0

解釋它,謝謝:) – Nat 2011-06-16 18:07:41

+1

你的例子也提供了一個UTF-8無效字節的字符串示例幫助我。謝謝! – Chris 2012-02-15 19:29:04

1

我在這裏未能在Linux上得到一個錯誤,即使輸入文件不是UTF-8的工作。 (我也使用Ruby 1.9.2)。

從邏輯上說,這個問題是與OS-X相關的,或者它與您的輸入數據有關。不管輸入文件中的數據是否發生?

(我知道這是不是一個正確的答案,但我缺乏代表到添加評論。既然沒有人迴應呢,我覺得這比沒有好...)

1

你讀該文件使用系統提供的默認編碼。所以紅寶石標記字符串爲utf8,這並不意味着它確實是utf8數據。嘗試file <input file>來猜測那裏是什麼樣的編碼,然後告訴ruby它是那個(不乾淨:force_encoding(<encoding>),clean:告訴File對象它是什麼編碼,我不知道該怎麼做),然後用encode!("utf8")轉換它到utf8

+0

,解釋它,謝謝:) – Nat 2011-06-16 18:06:46

+1

是否'file'處理整個文件,還是隻處理前n個字節?對我來說,這只是一個大塊,但這可能是我頭腦中過去的日子裏留下的一段記憶碎片。 – 2011-06-16 18:16:44

0

請試試這個: -

input_data = File.open( 「路徑/ your_file.pdf」, 「RB」){| IO | IO。閱讀}

感謝

0

這裏有兩個常見的情況,以及如何對付它們:

情況1

您有一個UTF-8輸入文件,可能具有幾無效字節
刪除無效字節:

test = "Partly valid\xE4 UTF-8 encoding: äöüß" 
File.open('input_file', 'w') {|f| f.write(test)} 

str = File.read('input_file') 

str.scrub('') 
    => "Partly valid UTF-8 encoding: äöüß" 

情況2

您有一個輸入文件,該文件可能是UTF-8或ISO-8859-1編碼或者
檢查其編碼它並轉換爲UTF-8(如果需要):

test = "String in ISO-8859-1 encoding: \xE4\xF6\xFC\xDF" 
File.open('input_file', 'w') {|f| f.write(test)} 

str = File.read('input_file') 

unless str.valid_encoding? 
    str.encode!('UTF-8', 'ISO-8859-1', invalid: :replace) 
end #unless 
    => "String in ISO-8859-1 encoding: äöüß" 


  • 的上面的代碼片段假定默認情況下,Ruby在UTF-8中編碼所有字符串。儘管這幾乎總是如此,但您可以通過# encoding: UTF-8開始腳本來確保這一點。

  • 如果無效,則可以通過編程方式檢測大多數多字節編碼,如UTF-8(在Ruby中,請參閱:#valid_encoding?)。但是,以編程方式檢測像ISO-8859-1這樣的單字節編碼的無效性是不可能的(或者至少非常困難)。因此,上述代碼片段不能以其他方式工作,即檢測字符串是否有效編碼ISO-8859-1

  • 即使UTF-8已經成爲在計算機系統中,ISO-8859-1Latin1味道仍然在西方國家非常流行,特別是在北美地區的默認編碼越來越受歡迎。請注意,有幾個單字節編碼非常相似,但與ISO-8859-1略有不同。例子:CP1252(又名Windows-1252),ISO-8859-15

[紅寶石] [編碼] [UTF-8] [文件編碼] [字符編碼]

相關問題