我尝试检测文件中使用了哪个字符编码。

我尝试使用此代码以获取标准编码

public static Encoding GetFileEncoding(string srcFile)
    {
      // *** Use Default of Encoding.Default (Ansi CodePage)
      Encoding enc = Encoding.Default;

      // *** Detect byte order mark if any - otherwise assume default
      byte[] buffer = new byte[5];
      FileStream file = new FileStream(srcFile, FileMode.Open);
      file.Read(buffer, 0, 5);
      file.Close();

      if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
        enc = Encoding.UTF8;
      else if (buffer[0] == 0xfe && buffer[1] == 0xff)
        enc = Encoding.Unicode;
      else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
        enc = Encoding.UTF32;
      else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
        enc = Encoding.UTF7;
      else if (buffer[0] == 0xFE && buffer[1] == 0xFF)      
        // 1201 unicodeFFFE Unicode (Big-Endian)
        enc = Encoding.GetEncoding(1201);      
      else if (buffer[0] == 0xFF && buffer[1] == 0xFE)      
        // 1200 utf-16 Unicode
        enc = Encoding.GetEncoding(1200);


      return enc;
    }

我的五个字节是60、118、56、46和49。

是否有图表显示编码哪个与这五个字节匹配的图表?

有帮助吗?

解决方案

您不能依靠BOM的文件。 UTF-8不需要它。而且非固定编码甚至没有BOM。但是,还有其他检测编码的方法。

UTF-32

BOM为00 00 fe ff(be)或ff fe 00 00(对于LE)。

但是即使没有BOM,UTF-32也很容易检测到。这是因为Unicode代码点范围仅限于U+10FFFF,因此UTF-32单元始终具有模式00 {00-10} XX XX(for Be)或XX XX XX {00-10} 00(用于LE) 。如果数据的长度为4的倍数,并且遵循这些模式之一,则可以安全地假设其是UTF-32。由于面向字节的编码中00字节的稀有性,误报几乎是不可能的。

美国

没有生物,但是您不需要。通过在80FF范围内缺少字节,可以轻松地识别ASCII。

UTF-8

BOM是EF BB BF。但是你不能依靠这个。许多UTF-8文件没有BOM,尤其是当它们起源于非窗口系统时。

但是您可以安全地假设,如果文件验证为UTF-8,则 UTF-8。误报很少见。

具体而言,鉴于数据不是ASCII,因此2字节序列的假阳性仅为3.9%(1920/49152)。对于7字节序列,它不到1%。对于12字节序列,它不到0.1%。对于24字节的序列,它不到一百万分之一。

UTF-16

BOM是Fe FF(用于BE)或FF FE(对于LE)。请注意,在UTF-32LE BOM的开头找到UTF-16LE BOM,因此请先检查UTF-32。

如果您碰巧拥有一个主要由ISO-8859-1字符组成的文件,则文件字节的一半为00也将是UTF-16的强烈指标。

否则,识别没有BOM的UTF-16的唯一可靠方法是寻找替代配对(D [8-B] XX D [CF] XX),但是非BMP字符很少使用,无法使这种方法实用。

XML

如果您的文件从字节3C 3F 78 6D 6C开始(即,ASCII字符” encoding= 宣言。如果存在,请使用该编码。如果不存在,则假设UTF-8,即默认XML编码。

如果您需要支持EBCDIC,也可以寻找等效序列4C 6F A7 94 93。

通常,如果您具有包含编码声明的文件格式,请查找该声明而不是试图猜测编码。

以上都不是

还有数百个其他编码,需要更多的努力来检测。我建议尝试 Mozilla的Charset探测器 或者 一个.NET端口.

合理的默认值

如果您排除了UTF编码,并且没有指向不同编码的编码声明或统计检测 ISO-8859-1 或密切相关的 Windows-1252. 。 (请注意,最新的HTML标准 需要 “ ISO-8859-1”声明要解释为Windows-1252。 UTF-8。

其他提示

如果您想寻求“简单”的解决方案,您可能会发现我组合在一起有用:

http://www.architectshack.com/textfileencodingdetector.ashx

它首先自动进行BOM检测,然后尝试区分无BOM的Unicode编码,与其他默认编码(通常Windows-1252,错误地标记为encoding.ascii in .NET中)。

如上所述,涉及nChardet或mlang的“更重”解决方案可能更合适,正如我在此类概述页面上注明的那样,最好的是在可能的话上提供与用户的某种形式的交互性,因为只有在这里,没有100%的检测率!

利用 StreamReader 并指导它为您检测编码:

using (var reader = new System.IO.StreamReader(path, true))
{
    var currentEncoding = reader.CurrentEncoding;
}

并使用 代码页标识符 https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(V=VS.85).aspx为了根据它切换逻辑。

这里有几个答案,但是没有人发布了有用的代码。

这是我的代码检测Microsoft在StreamReader类中检测到的所有编码。

显然,您必须在打开流之后立即调用此功能,然后再读取流中的其他内容,因为BOM是流中的第一个字节。

此功能需要一个可以寻找的流(例如文件流)。如果您有一个无法寻求的流,则必须编写一个更复杂的代码,该代码返回具有已经读取但不是BOM的字节的字节缓冲区。

/// <summary>
/// UTF8    : EF BB BF
/// UTF16 BE: FE FF
/// UTF16 LE: FF FE
/// UTF32 BE: 00 00 FE FF
/// UTF32 LE: FF FE 00 00
/// </summary>
public static Encoding DetectEncoding(Stream i_Stream)
{
    if (!i_Stream.CanSeek || !i_Stream.CanRead)
        throw new Exception("DetectEncoding() requires a seekable and readable Stream");

    // Try to read 4 bytes. If the stream is shorter, less bytes will be read.
    Byte[] u8_Buf = new Byte[4];
    int s32_Count = i_Stream.Read(u8_Buf, 0, 4);
    if (s32_Count >= 2)
    {
        if (u8_Buf[0] == 0xFE && u8_Buf[1] == 0xFF)
        {
            i_Stream.Position = 2;
            return new UnicodeEncoding(true, true);
        }

        if (u8_Buf[0] == 0xFF && u8_Buf[1] == 0xFE)
        {
            if (s32_Count >= 4 && u8_Buf[2] == 0 && u8_Buf[3] == 0)
            {
                i_Stream.Position = 4;
                return new UTF32Encoding(false, true);
            }
            else
            {
                i_Stream.Position = 2;
                return new UnicodeEncoding(false, true);
            }
        }

        if (s32_Count >= 3 && u8_Buf[0] == 0xEF && u8_Buf[1] == 0xBB && u8_Buf[2] == 0xBF)
        {
            i_Stream.Position = 3;
            return Encoding.UTF8;
        }

        if (s32_Count >= 4 && u8_Buf[0] == 0 && u8_Buf[1] == 0 && u8_Buf[2] == 0xFE && u8_Buf[3] == 0xFF)
        {
            i_Stream.Position = 4;
            return new UTF32Encoding(true, true);
        }
    }

    i_Stream.Position = 0;
    return Encoding.Default;
}

您应该阅读以下内容: 如何检测文本文件的编码/编码

如果您的文件以60、118、56、46和49的字节开始,则您有一个模棱两可的情况。它可以是UTF-8(无BOM)或任何单个字节编码,例如ASCII,ANSI,ISO-8859-1等。

我用 Ude 那是Mozilla通用Charset检测器的C#港口。它易于使用,并给出一些非常好的效果。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top