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

时间:2011-06-16 15:51:05

标签: ruby string encoding

我正在编写一个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

5 个答案:

答案 0 :(得分: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 ','

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

请尝试这个: -

  

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

由于

答案 4 :(得分: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-1和其他Latin1种口味在西方国家仍然非常受欢迎,尤其是北美。请注意,有几个单字节编码非常相似,但与ISO-8859-1略有不同。示例:CP1252(a.k.a。Windows-1252),ISO-8859-15

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