如何在Ruby 1.9中读取ANSI文本文件并将字符串转换为UTF-8?

时间:2011-05-12 01:31:26

标签: ruby encoding

我正在尝试使用Ruby 1.9读取文本文件并将它们转换为我自己的XML结构。我无法控制源文本文件,因此它们可以进行任何编码。

这就是我现在所做的事情:

lines = File.readlines(input_file)
lines.each do |line|
  #do something
end

我的文件包含é字符(xE9)时遇到问题。当我尝试处理相应的行时,我在字符串上调用Invalid byte sequence in UTF-8时会出现.match(...)异常。

我尝试使用Fixing invalid UTF-8 in Ruby, revisited

中描述的解决方法
lines = File.readlines(input_file)
ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
lines.each do |line|
  unless line.empty?
   valid_string = ic.iconv(line + ' ')[0..-2]
   #do something
  end
end

但这只是从行中删除é字符而不是我想要的。

我认为真正的问题是文件本身似乎不是UTF-8,而是使用一些ANSI编码。虽然文件不是UTF-8,但生成的行对象在调用.encoding时表示它是UTF-8;我的猜测是我需要使用不同的方式来读取文件,以便它适用于ANSI和UTF-8文件,但我是Ruby初学者,我真的不知道从哪里开始。

2 个答案:

答案 0 :(得分:3)

该字符是others中ISO-8859-1和Win-1252字符集的一部分。第二个可能是Windows最受欢迎的字符集,并且是您最有可能的来源。

RUBY_VERSION # => "1.9.2"

这是我的Ruby版本运行以下测试。请注意,在以下示例中,# encoding行不是注释,它们是指向Ruby的指令,在找到未编码的二进制字符时使用哪个字符集:

# encoding: Windows-1252

RUBY_VERSION # => "1.9.2"

asdf = "\xe9"
asdf.encoding # => #<Encoding:Windows-1252>
asdf.encode('UTF-8') # => "é"
asdf.encode('UTF-8').encoding # => #<Encoding:UTF-8>

这显示了ISO-8859-1中的字符:

# encoding: ISO-8859-1

RUBY_VERSION # => "1.9.2"

asdf = "\xe9"
asdf.encoding # => #<Encoding:ISO-8859-1>
asdf.encode('UTF-8') # => "é"
asdf.encode('UTF-8').encoding # => #<Encoding:UTF-8>
几年前,詹姆斯·格雷(James Gray)做了series of articles关于处理这些事情的事。这是很好的阅读。

现在,回到试图弄清楚角色可能在哪个角色集中:当你只有一个角色,因为它可能同时在几个集合中,很难确定它是哪个集合。如果您有更多字符&gt; =“\ x80”,那么您可以浏览字符集iconv支持并尝试转换它们。这很麻烦,但我不得不在Perl中做这个,大约在五年前进行一些屏幕刮擦。另一种方法是使用Python chardet代码。

James Gray的文章链接到推荐rchardet的文章。

以上例程提到了Mozilla的Charset Detectors,它将为您提供有关处理此问题的更多信息。

答案 1 :(得分:2)

你可以在控制台上试试,这可能是一个暗示:

我使用这样的系统命令来执行此操作:

iconv -f windows-1252 -t UTF-8 "#{csv_file}" > #{Rails.root}/tmp/Kdvakanz-utf8.csv