Ruby 1.8 Iconv UTF-16到UTF-8失败,带有“\ 000”(Iconv :: InvalidCharacter)

时间:2011-05-30 03:44:52

标签: ruby utf-8 character-encoding utf-16 iconv

我无法处理在Windows机器上生成的列表数据的文本文件。 我在Ruby 1.8工作。当从文件处理SECOND行时,以下给出错误(“\ 000”(Iconv :: InvalidCharacter))。第一行正确转换。

require 'iconv'
conv = Iconv.new("UTF-8//IGNORE","UTF-16")
infile = File.open(tabfile, "r")
while (line = infile.gets)
  line = conv.iconv(line.strip)  # FAILS HERE
  puts line
  # DO MORE STUFF HERE
end

奇怪的是它读取并转换文件中的第一行没有问题。 我在Iconv构造函数中有// IGNORE标志 - 我认为这应该可以抑制这种错误。

我已经进入了一段时间。任何建议都将受到高度赞赏。

谢谢!

编辑: hobbs解决方案解决了这个问题。谢谢。 只需将代码更改为:

require 'iconv'
conv = Iconv.new("UTF-8//IGNORE","UTF-16")
infile = File.open(tabfile, "r")
while (line = infile.gets("\x0a\x00"))
  line = conv.iconv(line.strip)  # NO LONGER FAILS HERE
  # DOES MORE STUFF HERE
end

现在我只需要找到一种方法来自动确定使用哪个分隔符。

2 个答案:

答案 0 :(得分:6)

错误信息非常模糊,但我认为它在一条线路上找到奇数字节数这一事实感到不满,因为UTF-16中的每个字符都是两个(或偶尔为四个字符) )字节。我认为 的原因是你使用gets - 文件中的行由UTF-16le换行符分隔,0x0a 0x00,但是{{ 1}}正在拆分(gets正在移除)strip仅限。{/ p>

举例说明:假设文件包含

0x0a

以UTF-16le编码。那是

ab
cd

0x61 0x00 0x62 0x00 0x0a 0x00 0x63 0x00 0x64 0x00 0x0a 0x00 a b \n c d \n 读取gets0x0a删除,因此读取的第一行是strip,iconv很乐意接受并编码为UTF-8 0x61 0x00 0x62 0x00 - “ab”。 0x61 0x62然后读取下一个gets 0x0astrip再次删除,所以第二次line获得0x00 0x63 0x00 0x64 0x00现在一切都被搞砸了 - 我们'与一个字节不同步,并且有一个奇数个字节要转换,iconv会爆炸,因为这与你要求它做的不相容。

如果没有实际工作文件编码/解码层,我认为你想要的是将gets分隔符从"\n""\x0a")更改为"\x0a\x00",放弃所有使用strip,因为它不是编码干净的,并且使用print代替puts,因此您不会添加额外的行尾(因为您将转换那些'已经有了。)

如果您正在使用Windows文件,则UTF-16le中的Windows CRLF为"\x0d\x00\x0a\x00"

答案 1 :(得分:0)

上面的答案很好。您还可以在逐行处理之前将整个文件转换为UTF-8,但这可能会对大型文件产生更糟糕的流式传输行为。

相关问题