首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >猜测日志文件中字节流的字符串编码

猜测日志文件中字节流的字符串编码
EN

Stack Overflow用户
提问于 2012-02-13 18:09:39
回答 3查看 529关注 0票数 4

tl;dr汇总:给定一个以未知编码方式表示字符串的字节流,我应该尝试按什么顺序解释这些字节,以获得找到“正确”编码的最佳机会?

这个问题的例子

我有一个文件arrows.txt,我碰巧知道它是用的单字符内容使用UTF-8保存的。如果我假装不知道该文件的编码是什么,Windows上的以下Ruby代码就会失败:

代码语言:javascript
复制
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为每一行尝试各种编码,以找到一个有效且可能(当然不是保证)正确的编码。

失败尝试

我最初编写了以下代码:

代码语言:javascript
复制
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?成为正确的编码?对于使用的字节,哪种编码是最挑剔的,比如我应该先尝试它们,哪些公共编码是完全允许的,所以我应该最后尝试它们?

在猜测正确性时还有什么其他的试探方法吗?(如果一个特定的编码比另一个编码的字符少,那么它更有可能是正确的吗?)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-13 19:11:52

您可以尝试rchardet19宝石。它“在未知字符编码中获取一个字节序列,并尝试确定编码。”它还为它返回的编码提供了一个信任评分。在过去,它对我起了好几次作用,看起来它能完成你想要完成的任务。

示例用法:

代码语言:javascript
复制
require 'rchardet19'
cd = CharDet.detect("some data")
# => #<struct #<Class:0x102216198> encoding="ascii", confidence=1.0>
票数 2
EN

Stack Overflow用户

发布于 2012-02-13 18:53:23

如果您的代码可以在unix/linux机器上运行,那么丝状 gem可能会很适合您。

代码语言:javascript
复制
gem install ruby-filemagic

它是确定整个文件编码的最有用的工具,然后可以用于文件中的所有行。以下内容将帮助您开始使用它:

代码语言:javascript
复制
$ 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>
票数 1
EN

Stack Overflow用户

发布于 2012-02-13 18:53:51

当我处理写蜘蛛的时候,我总是从ISO-8859-1开始,然后是Win-1252。两者之间的差别很小,所以在大多数情况下都应该是合适的。我的第一个理由是,我认为你最有可能遇到他们。

如果有些东西不符合这些要求,那么我就用iconv把它转换成UTF-8,或者去掉对话口音,这样它在视觉上就像我们期望看到的一样,然后继续。

有些时候,没有什么是成功的;我有一些代码,它提取了偶像的所有编码,然后删除了所有的ASCII值,并试图为剩下的字符找到具有最高命中次数的编码。XML和HTML有时会出现格式错误,以致于没有任何帮助,当我恢复到消除口音的时候。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9265605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档