3

我在处理 Windows 机器上生成的表格数据的文本文件时遇到问题。我正在使用 Ruby 1.8。在处理文件中的第二行时,以下给出错误 ("\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 标志——我认为这应该抑制这种错误。

我一直在兜圈子。任何建议将不胜感激。

谢谢!

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

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

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

4

2 回答 2

6

错误消息非常模糊,但我认为它在一行上发现奇数个字节这一事实令人不快,因为 UTF-16 中的每个字符都是两个(或偶尔四个)字节。我认为这样做的原因您使用了gets-- 文件中的行由 UTF-16le 换行符分隔,即0x0a 0x00, 但gets仅拆分(并且strip正在删除)0x0a

举例说明:假设文件包含

ab
cd

以 UTF-16le 编码。那是

0x61 0x00 0x62 0x00 0x0a 0x00 0x63 0x00 0x64 0x00 0x0a 0x00
    a         b         \n        c         d         \n

gets读取到 first 0x0a,它被strip删除,所以第一行读取的是0x61 0x00 0x62 0x00,iconv 很高兴地接受它并将其编码为 UTF-8 为0x61 0x62-“ab”。gets然后读到下一个0x0a,它strip再次被删除,所以第二次line得到0x00 0x63 0x00 0x64 0x00,现在一切都搞砸了——我们不同步一个字节,有奇数个字节要转换,然后iconv爆炸,因为这与什么不兼容你要求它做。

没有一个实际的工作文件编码/解码层,我认为你想要的是将gets分隔符从"\n"( "\x0a") 更改为"\x0a\x00",放弃所有使用,strip因为它不是编码干净的,而是使用print而不是puts这样你就不会添加额外的行-结束(因为你将转换你已经得到的那些)。

如果您使用的是 windows 文件,则 UTF-16le 中的 windows CRLF 是"\x0d\x00\x0a\x00".

于 2011-05-30T04:10:36.373 回答
0

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

于 2011-05-31T02:51:40.790 回答