Java:如何从inputStream中获取编码?

13

我想从流中获取编码。

第一种方法 - 使用InputStreamReader。

但它总是返回操作系统的编码。

InputStreamReader reader = new InputStreamReader(new FileInputStream("aa.rar"));
System.out.println(reader.getEncoding());

输出:GBK

第二种方法 - 使用UniversalDetector。

但它总是返回null。

    FileInputStream input = new FileInputStream("aa.rar");

    UniversalDetector detector = new UniversalDetector(null);
    byte[] buf = new byte[4096];

    int nread;
    while ((nread = input.read(buf)) > 0 && !detector.isDone()) {
        detector.handleData(buf, 0, nread);
    }

    // (3)
    detector.dataEnd();

    // (4)
    String encoding = detector.getDetectedCharset();

    if (encoding != null) {
        System.out.println("Detected encoding = " + encoding);
    } else {
        System.out.println("No encoding detected.");
    }

    // (5)
    detector.reset();

输出:null

我该如何得到正确的结果?:(


4
InputStreamReader始终使用平台编码,不会尝试检测文件的编码格式。 您正在通过UniversalDetector运行哪种类型的文件?在您的示例中,您使用了RAR文件,这是一种压缩二进制格式。请先尝试使用简单的ASCII文本文件。 - prunge
嗨,我已经更改了文件类型,“Fortunes.txt”输出:未检测到编码。 - youzhi.zhang
它似乎无法检测没有BOM的“标准”UTF-8或UTF-16,但对于带有BOM的UTF-16,它对我有效。也许考虑使用不同的库进行字符集检测?这个链接可能会有所帮助。 - prunge
3
仅通过检查文本数据来检测编码是不可靠的猜测。确保准确,您需要在元数据中指定编码。 - Michael Borgwardt
@Michael Borwardt:但在许多情况下,您没有任何指定编码的元数据,也没有任何规范告诉您需要解析的txt文件将以哪种编码进行编码。在这些情况下,像http://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html这样的工具所做的“猜测”(使用字母频率以及许多其他启发式方法)似乎是相当“科学”的猜测。一切并不总是非黑即白。当您没有元数据时,您不会说:“我需要元数据”,而是努力工作并编写(或重用)检测器。 - TacticalCoder
2个回答

7
让我们回顾一下情况:
  • InputStream提供字节
  • *Readers以某种编码提供字符
  • new InputStreamReader(inputStream)使用操作系统编码
  • new InputStreamReader(inputStream,“UTF-8”)使用给定的编码(这里是UTF-8)
因此,在读取之前需要知道编码。您使用了一个字符集检测类,做得很正确。
阅读http://code.google.com/p/juniversalchardet/,它应该处理UTF-8和UTF-16。 您可以使用编辑器JEdit来验证编码,并查看是否存在任何问题。

我们可以使用其他工具来实现,但它无法理解特定的处理方法,似乎只是应付了事。 :( - youzhi.zhang
Juniversalchardet 不支持 ISO-8859-1,而这是一种非常常见的字符集。 - Thomas
@Thomas universalchardet 源自浏览器领域,其中 ISO-8859-1 被重新解释为 Windows-1252(自 HTML 5 官方推荐),因此也许 Window-1252 aka Cp1252 可以使用。是的,已经检查过了。 - Joop Eggen

0
    public String getDecoder(InputStream inputStream) {

    String encoding = null;

    try {
        byte[] buf = new byte[4096];
        UniversalDetector detector = new UniversalDetector(null);
        int nread;

        while ((nread = inputStream.read(buf)) > 0 && !detector.isDone()) {
            detector.handleData(buf, 0, nread);
        }

        detector.dataEnd();
        encoding = detector.getDetectedCharset();
        detector.reset();

        inputStream.close();

    } catch (Exception e) {
    }

    return encoding;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接