tl; dr summary :给定一个字节流,表示未知编码中的字符串,我应该尝试编码的字节数和顺序,以便最有可能找到'对'编码?
我有一个文件arrows.txt
我碰巧知道使用UTF-8保存了单字符内容⇈
。如果我假装我不知道该文件的编码是什么,则Windows上的以下Ruby代码将失败:
s = IO.read('foo.txt')
p s.encoding, #=> #<Encoding:IBM437>
s.valid_encoding?, #=> true
s.chars.to_a #=> ["\xE2", "\x87", "\x88"]
它'失败'因为它告诉我文件实际上有内容Γçê
,并且一切正常(编码有效)。
我有Nginx个日志文件和Akamai日志文件,这些文件对他们记录的查询没有任何特定的编码,我需要以UTF-8的形式处理和存储数据库中的数据。大多数时候将每一行解释为UTF-8会产生一个带有有效编码的字符串,但有时它不会。
我想让Ruby为每一行尝试各种编码,找到一个有效且可能(但当然不能保证)正确的编码。
我最初编写了以下代码:
def guess_encoding( str, result='utf-8', *encodings )
# Try every encoding if none were passed in
encodings = Encoding.list if encodings.empty?
# Keep forcing a new encoding until we find one that is valid
unless encodings.find{ |e| str.force_encoding(e) && str.valid_encoding? }
raise "None of the supplied encodings was valid"
end
# Convert from the valid encoding to the desired, replacing 'bad' characters
str.encode(result, invalid: :replace, undef: :replace)
end
问题在于Encoding.list
中的第一个编码是ASCII-8BIT
,它对所有字节流都有效。因此,如果我使用上面的代码并调用s2 = guess_encoding(s)
,结果就是上面我的三字节双箭头字符的字符串���
。
我应该以什么顺序测试编码,以便最有可能让第一个valid_encoding?
成为正确的编码?哪些常见的编码是最常用的字节,所以我应该首先尝试它们,哪些常见的编码是完全允许的,这样我应该最后一次尝试?
我是否应该使用其他启发式方法来猜测正确性? (如果特定编码导致的字符数少于另一个,那么它更可能是正确的吗?)
答案 0 :(得分:2)
你可以试试rchardet19宝石。它“在未知字符编码中采用一系列字节,并尝试确定编码。”它还为您返回的编码提供置信度分数。它过去曾为我工作过好几次,看起来就像你想要完成的那样。
使用示例:
require 'rchardet19'
cd = CharDet.detect("some data")
# => #<struct #<Class:0x102216198> encoding="ascii", confidence=1.0>
答案 1 :(得分:1)
如果你的代码可以在unix / linux机器上运行,那么filemagic gem可能适合你。
gem install ruby-filemagic
最有用的工具是确定整个文件的编码,然后可以将其用于文件中的所有行。以下内容可以帮助您开始使用它:
$ irb
irb(main):001:0> require 'filemagic'
=> true
irb(main):002:0> fm = FileMagic.new
=> #<FileMagic:0x7fd4afb0>
irb(main):003:0> fm.file('afile.zip')
=> "Zip archive data, at least v2.0 to extract"
irb(main):004:0>
答案 2 :(得分:1)
当我处理写蜘蛛时,我总是先用ISO-8859-1开始,然后是Win-1252。两者之间的差异很小,因此大多数时候要么适合。我之所以这么做,我认为你最有可能遇到它们。
如果某些内容不适合那些,那么我只需使用iconv将其转换为UTF-8,或者删除变音符号,使其在视觉上与我们期望看到的相似,然后继续。
有时候什么都不会受到打击;我有代码提取了所有iconv的编码,然后剥离了所有的ASCII值,并试图找到剩余字符的最高命中数的编码。 XML和HTML偶尔也会如此畸形,以至于没有任何帮助,这就是当我恢复剥离重音时。