猜测java中以byte[]表示的文本的编码

yv5phkfx  于 2021-06-30  发布在  Java
关注(0)|答案(7)|浏览(481)

给定一个表示未知编码(通常是utf-8或iso-8859-1,但不一定如此)中文本的字节数组,获得最可能使用的编码猜测的最佳方法是什么(在java中)?
值得注意的是:
没有其他元数据可用。字节数组实际上是唯一可用的输入。
检测算法显然不是100%正确的。如果算法在80%以上的情况下是正确的,那就足够了。

h79rfbju

h79rfbju1#

应该已经有东西了
谷歌搜索发现了icu4j

http://jchardet.sourceforge.net/

pdtvr36n

pdtvr36n2#

如果没有编码指示符,您将永远无法确定。不过,你可以做出一些明智的猜测。看看我对这个问题的回答,
如何确定字符串是否包含无效的编码字符
使用validutf8()方法。如果返回true,则将其视为utf8,否则视为拉丁语-1。

q9yhzks0

q9yhzks03#

我最喜欢的是:https://github.com/codehaus/guessencoding
工作原理如下:
如果有utf-8或utf-16物料清单,则返回该编码。
如果没有字节设置高位,则返回ascii(也可以强制它返回默认的8位编码)。
如果存在高位设置的字节,但它们以正确的utf-8模式排列,则返回utf-8。
否则,返回平台默认编码(例如,英语区域设置windows系统上的windows-1252)。
这听起来可能过于简单,但在我的日常工作中,它的准确率远远超过90%。

bmvo0sr5

bmvo0sr54#

下面的方法使用juniversalchardet解决了这个问题,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;
}

上面的代码已经过测试,并按预期工作。只需将juniversalchardet-1.0.3.jar添加到类路径。
我测试了juniversalchardet和jchardet。我的总体印象是juniversalchardet提供了两个库中更好的检测精度和更好的api。

vjhs03f7

vjhs03f75#

池的答案似乎最有希望用于实际应用。我只想补充一点,据joel spolsky说,internet explorer在它的时代使用了一种基于频率的猜测算法:
http://www.joelonsoftware.com/articles/unicode.html
粗略地说,所有假定为文本的内容都被复制,并以每一种可以想象的编码方式进行解析。无论哪种语法最符合一种语言的平均单词(和字母?)频率分布,都会获胜。我不能很快看出jchardet是否使用相同的方法,所以我想我应该提到这一点以防万一。

nr7wwzry

nr7wwzry6#

还有ApacheTika—一个内容分析工具包。它可以猜测mime类型,也可以猜测编码。通常猜测是正确的,概率很高。

相关问题