【问题标题】:Guessing the encoding of text represented as byte[] in Java猜测在 Java 中表示为 byte[] 的文本的编码
【发布时间】:2009-11-04 23:54:03
【问题描述】:

给定一个以某种未知编码(通常为 UTF-8 或 ISO-8859-1,但不一定如此)表示文本的字节数组,猜测最可能使用的编码的最佳方法是什么(在 Java )?

值得注意的是:

  • 没有额外的元数据可用。字节数组实际上是唯一可用的输入。
  • 检测算法显然不会 100% 正确。如果算法在 80% 以上的情况下是正确的,那就足够了。

【问题讨论】:

标签: java encoding utf-8 character-encoding


【解决方案1】:

以下方法使用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 添加到类路径即可。

我已经测试了juniversalchardetjchardet。我的总体印象是,juniversalchardet 提供了两个库中更好的检测精度和更好的 API。

【讨论】:

  • 我的项目要求是,如果数据不是utf8(检测后)然后转成utf8,怎么办?
  • @coding_idiot 使用“猜测”编码转换为字符串,然后得到 utf-8 字节:new String(bytes, guessedEncoding).getBytes("utf-8")
  • juniversalchardet 在 maven 中也可用。 groupId:com.googlecode.juniversalchardet,art​​ifactId:juniversalchardet。
【解决方案2】:

还有Apache Tika - a content analysis toolkit。它可以猜测 mime 类型,也可以猜测编码。通常猜测是正确的概率非常高。

【讨论】:

    【解决方案3】:

    这是我最喜欢的:https://github.com/codehaus/guessencoding

    它是这样工作的:

    • 如果有 UTF-8 或 UTF-16 BOM,则返回该编码。
    • 如果所有字节都没有设置高位,则返回 ASCII(或者您可以强制它返回默认的 8 位编码)。
    • 如果存在设置了高位的字节,但它们以正确的 UTF-8 模式排列,则返回 UTF-8。
    • 否则,返回平台默认编码(例如,英语区域设置 Windows 系统上的 windows-1252)。

    这听起来可能过于简单,但在我的日常工作中,它的准确率远远超过 90%。

    【讨论】:

      【解决方案4】:

      Chi 的答案似乎最有希望用于实际使用。我只想补充一点,根据 Joel Spolsky 的说法,Internet Explorer 在当时使用了一种基于频率的猜测算法:

      http://www.joelonsoftware.com/articles/Unicode.html

      粗略地说,所有假定的文本都被复制,并以可以想象的每种编码进行解析。无论哪种解析最适合一种语言的平均单词(和字母?)频率分布,都会获胜。我不能很快看出 jchardet 是否使用相同的方法,所以我想我会提到这一点以防万一。

      【讨论】:

        【解决方案5】:

        查看jchardet

        【讨论】:

        • 请详细说明 - 为什么您认为 jchardet 是最好的库?
        • @chi如果编码不是utf8怎么转成utf8。
        【解决方案6】:

        应该是已经可用的东西

        谷歌搜索出现了 icu4j

        http://jchardet.sourceforge.net/

        【讨论】:

        • 我有点知道如何使用谷歌,但这个问题特别问“什么是最好的方法 [..]”。那么哪个最好,icu4j、jchardet 还是其他库?
        【解决方案7】:

        如果没有编码指示符,您将永远无法确定。但是,您可以做出一些明智的猜测。请参阅我对这个问题的回答,

        How to determine if a String contains invalid encoded characters

        使用有效的UTF8() 方法。如果返回 true,则将其视为 UTF8,否则视为 Latin-1。

        【讨论】:

        • 不是UTF-8的情况怎么办?
        • 如果不是 UTF-8,一味地称它为 Latin-1 不是一个好主意。最好使用 ICU、jchardet 或此页面上列出的其他工具之一进行智能猜测。
        猜你喜欢
        • 1970-01-01
        • 2011-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-16
        • 2015-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多