猜测在Java中表示为byte 的文本的编码
给定一些代表某些未知编码(通常是UTF-8或ISO-8859-1,但不一定如此)的文本的字节数组,最好的方法是获得最可能使用的编码(在Java中)的猜测?
值得注意:
- 没有额外的元数据可用。 字节数组实际上是唯一可用的input。
- 检测algorithm显然不是100%正确的。 如果algorithm在80%以上的情况下是正确的,那就足够了。
下面的方法使用juniversalchardet来解决这个问题,它是Mozilla编码检测库的Java端口。
public static String guessEncoding(byte[] bytes) { String DEFAULT_ENCODING = "UTF-8"; org.mozilla.universalchardet.UniversalDetector detector = new org.mozilla.universalchardet.UniversalDetector(null); detector.handleData(bytes, 0, bytes.length); detector.dataEnd(); String encoding = detector.getDetectedCharset(); detector.reset(); if (encoding == null) { encoding = DEFAULT_ENCODING; } return encoding; }
上面的代码已经过testing,并按照预期工作。 只需将juniversalchardet-1.0.3.jar添加到类path即可。
我已经testing了juniversalchardet和jchardet 。 我的一般印象是juniversalchardet提供了更好的检测精度和更好的API两个库。
还有Apache Tika–一个内容分析工具包 。 它可以猜测的MIMEtypes,它可以猜测编码。 通常这个猜测是正确的,而且可能性很高。
这是我的最爱: http : //glaforge.free.fr/wiki/index.php?wiki=GuessEncoding
它是这样工作的:
- 如果有UTF-8或UTF-16 BOM,则返回该编码。
- 如果没有任何字节设置了高位,则返回ASCII(或者强制它返回默认的8位编码)。
- 如果有高位设置的字节,但是它们以正确的UTF-8模式排列,则返回UTF-8。
- 否则,返回平台的默认编码(例如,在英语区域Windows系统上的windows-1252)。
这听起来可能过于简单,但在我的日常工作中,精确度超过了90%。
智的答案似乎最有希望的实际使用。 我只想补充一点,根据Joel Spolsky的说法,Internet Explorer在当天使用了基于频率的猜测algorithm:
http://www.joelonsoftware.com/articles/Unicode.html
粗略地说,所有假设的文本被复制,并在每个可以想象的编码中被parsing。 无论哪种parsing都适合一种语言的平均单词(和字母?)频率概况最好,胜。 我不能很快看到jchardet是否使用了同样的方法,所以我想我会提到这一点,以防万一。
看看jchardet
没有编码指标,你永远不会知道。 但是,你可以做一些聪明的猜测。 看到我对这个问题的回答,
如何确定一个string是否包含无效的编码字符
使用validUTF8()方法。 如果它返回true,则将其视为UTF8,否则视为Latin-1。