为什么在读取文本文件时出现“UTF-8中的无效字节序列”错误?

我正在编写一个Ruby脚本来处理一个大文本文件,并继续得到奇怪的编码错误。 这是情况:

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

显然你的输入文件不是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 ',' 

即使输入文件不是UTF-8,我也无法在Linux上收到错误。 (我也在使用Ruby 1.9.2。)

逻辑上,这个问题与OS-X有关,或者与输入数据有关。 是否与输入文件中的数据无关?

(我意识到这不是一个正确的答案,但我没有代表添加评论。而且由于没有人回应,我认为它总比没有好……)

您使用系统提供的默认编码读取文件。 所以ruby将字符串标记为utf8 ,这并不意味着它真的是utf8数据。 尝试file 来猜测那里有什么样的编码,然后告诉ruby它是那个(不干净: force_encoding() ,干净:告诉File对象它是什么编码,我不知道如何做那个)然后使用encode!("utf8")将其转换为utf8

请试试这个:-

input_data = File.open(“path / your_file.pdf”,“rb”){| io | io.read}

谢谢

以下是两种常见情况以及如何处理它们:

情况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等单字节编码的无效性是不可能的(或至少非常困难)。 因此,上面的代码片段不起作用,即检测String是否是有效的ISO-8859-1编码。

  • 尽管UTF-8作为计算机系统中的默认编码越来越受欢迎,但ISO-8859-1和其他Latin1种口味在西方国家仍然非常流行,特别是在北美。 请注意,有几个单字节编码非常相似,但与ISO-8859-1略有不同。 示例: CP1252 (又名Windows-1252 ), ISO-8859-15

[ruby] [编码] [utf8] [文件编码] [字符编码]