在我们的应用程序中,我们从不同的来源接收文本文件(.txt, .csv等)。读取时,这些文件有时包含垃圾,因为这些文件是在不同的/未知的代码页中创建的。

是否有一种方法(自动)检测文本文件的代码页?

detectEncodingFromByteOrderMarks,在StreamReader构造函数上,适用于UTF8和其他unicode标记的文件,但我正在寻找一种方法来检测代码页,如ibm850, windows1252。


谢谢你的回答,这就是我所做的。

我们收到的文件来自最终用户,他们没有关于代码页的线索。接收者也是最终用户,到目前为止,这是他们对代码页的了解:代码页存在,并且令人讨厌。

解决方案:

在记事本中打开收到的文件,查看一段乱码的文本。如果有人叫François之类的,凭你的智商你就能猜出来。 我已经创建了一个小应用程序,用户可以使用它打开文件,并输入用户知道它将出现在文件中的文本,当使用正确的代码页时。 遍历所有代码页,并显示包含用户提供的文本的解决方案的代码页。 如果多个代码页同时弹出,请用户指定更多文本。


当前回答

遇到了同样的问题,但还没有找到一个自动检测的好解决方案。 现在我使用PsPad (www.pspad.com)为那;)工作正常

其他回答

如果您正在寻找检测非utf编码(即没有BOM),那么您基本上需要对文本进行启发式和统计分析。您可能想看一看Mozilla关于通用字符集检测的论文(相同的链接,通过Wayback Machine有更好的格式)。

在寻找不同的解决方案时,我发现

https://code.google.com/p/ude/

这个溶液有点重。

我需要一些基本的编码检测,基于4个第一个字节和可能的xml字符集检测-所以我从互联网上取了一些样本源代码,并添加了稍微修改的版本

http://lists.w3.org/Archives/Public/www-validator/2002Aug/0084.html

为Java编写的。

    public static Encoding DetectEncoding(byte[] fileContent)
    {
        if (fileContent == null)
            throw new ArgumentNullException();

        if (fileContent.Length < 2)
            return Encoding.ASCII;      // Default fallback

        if (fileContent[0] == 0xff
            && fileContent[1] == 0xfe
            && (fileContent.Length < 4
                || fileContent[2] != 0
                || fileContent[3] != 0
                )
            )
            return Encoding.Unicode;

        if (fileContent[0] == 0xfe
            && fileContent[1] == 0xff
            )
            return Encoding.BigEndianUnicode;

        if (fileContent.Length < 3)
            return null;

        if (fileContent[0] == 0xef && fileContent[1] == 0xbb && fileContent[2] == 0xbf)
            return Encoding.UTF8;

        if (fileContent[0] == 0x2b && fileContent[1] == 0x2f && fileContent[2] == 0x76)
            return Encoding.UTF7;

        if (fileContent.Length < 4)
            return null;

        if (fileContent[0] == 0xff && fileContent[1] == 0xfe && fileContent[2] == 0 && fileContent[3] == 0)
            return Encoding.UTF32;

        if (fileContent[0] == 0 && fileContent[1] == 0 && fileContent[2] == 0xfe && fileContent[3] == 0xff)
            return Encoding.GetEncoding(12001);

        String probe;
        int len = fileContent.Length;

        if( fileContent.Length >= 128 ) len = 128;
        probe = Encoding.ASCII.GetString(fileContent, 0, len);

        MatchCollection mc = Regex.Matches(probe, "^<\\?xml[^<>]*encoding[ \\t\\n\\r]?=[\\t\\n\\r]?['\"]([A-Za-z]([A-Za-z0-9._]|-)*)", RegexOptions.Singleline);
        // Add '[0].Groups[1].Value' to the end to test regex

        if( mc.Count == 1 && mc[0].Groups.Count >= 2 )
        {
            // Typically picks up 'UTF-8' string
            Encoding enc = null;

            try {
                enc = Encoding.GetEncoding( mc[0].Groups[1].Value );
            }catch (Exception ) { }

            if( enc != null )
                return enc;
        }

        return Encoding.ASCII;      // Default fallback
    }

从文件中读取1024字节就足够了,但我加载的是整个文件。

遇到了同样的问题,但还没有找到一个自动检测的好解决方案。 现在我使用PsPad (www.pspad.com)为那;)工作正常

10年(!)已经过去了,我仍然没有看到MS的好的、非gpl的解决方案:IMultiLanguage2 API。

前面提到的大多数库都是基于Mozilla的UDE的——浏览器已经解决了类似的问题,这似乎是合理的。我不知道chrome的解决方案是什么,但自从IE 5.0 MS发布了他们的解决方案,它是:

没有gpl之类的许可问题, 可能是永远的支持和维护 给出丰富的输出-所有编码/编码页的有效候选以及置信度分数, 非常容易使用(它是一个单一的函数调用)。

它是一个原生COM调用,但这里有Carsten Zeumer的一些非常好的工作,它处理了。net使用中的互操作混乱。周围还有一些其他的图书馆,但总的来说,这个图书馆没有得到应有的关注。

我在Python中做过类似的事情。基本上,您需要来自各种编码的大量示例数据,这些数据由一个滑动的两字节窗口分解并存储在字典(散列)中,以提供编码列表值的字节对为键值。

给定这个字典(哈希),你把你的输入文本:

如果它以任何BOM字符开头('\xfe\xff'用于UTF-16-BE, '\xff\xfe'用于UTF-16-LE, '\xef\xbb\xbf'用于UTF-8等),我将其视为建议 如果不是,那么取足够大的文本样本,取样本的所有字节对,并选择从字典中建议的最不常见的编码。

如果您还采样了不以任何BOM开头的UTF编码文本,那么第二步将涵盖从第一步中遗漏的文本。

到目前为止,它对我来说是有效的(示例数据和后续输入数据是各种语言的字幕),错误率正在降低。