Pregunta

Me intenta detectar el tipo de codificación de caracteres se utiliza en mi archivo.

Trato con este código para obtener el estándar de codificación

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;
    }

Mis cinco primer byte son 60, 118, 56, 46 y 49.

¿Hay un gráfico que muestra qué codificación coincida con esas cinco primeros bytes?

¿Fue útil?

Solución

Usted no puede depender del archivo que tiene una lista de materiales. UTF-8 no lo requiere. Y codificaciones no Unicode no tienen ni siquiera una lista de materiales. Hay, sin embargo, otras formas de detectar la codificación.

UTF-32

lista de materiales es 00 00 FE FF (BE) o FF FE 00 00 (para LE).

Pero UTF-32 es fácil de detectar, incluso sin una lista de materiales. Esto es porque el intervalo de punto de código Unicode está restringido a U + 10FFFF, y por lo tanto UTF-32 unidades siempre tienen el patrón 00 {00-10} xx xx (para BE) o xx xx {00-10} 00 (por LE) . Si los datos tienen una longitud que es un múltiplo de 4, y sigue uno de estos patrones, se puede asumir con seguridad que de UTF-32. Los falsos positivos son casi imposibles debido a la rareza de 00 bytes de codificaciones orientados a bytes.

US-ASCII

No hay lista de materiales, pero no necesita una. ASCII se puede identificar fácilmente por la falta de bytes en el rango de 80-FF.

UTF-8

BOM es EF BB BF. Pero no se puede confiar en esta. Un montón de archivos UTF-8 no tienen una lista de materiales, especialmente si se hubieran originado en sistemas que no sean Windows.

Sin embargo, se puede suponer con seguridad que si un archivo valida como UTF-8, que es UTF-8. Los falsos positivos son raros.

Específicamente, dado que los datos no son ASCII, la tasa de falsos positivos para una secuencia de 2-byte es sólo el 3,9% (1920/49152). Para una secuencia de 7 bytes, es menos de 1%. Para una secuencia de 12 bytes, que es menos de 0,1%. Para una secuencia de 24 bytes, que es inferior a 1 en un millón.

UTF-16

BOM es FE FF (para BE) o FF FE (por LE). Tenga en cuenta que el UTF-16LE lista de materiales se encuentra en el inicio de la UTF-32LE lista de materiales, a fin de comprobar UTF-32 por primera vez.

Si le sucede que tiene un archivo que se compone principalmente de caracteres ISO-8859-1, teniendo la mitad de bytes del archivo sea 00 sería también un fuerte indicador de UTF-16.

De lo contrario, la única manera confiable de reconocer UTF-16 sin una lista de materiales es la búsqueda de pares suplentes (D [8-B] xx D [CF] xx), pero no BMP personajes están muy raramente utilizado para hacer este enfoque práctico.

XML

Si el archivo se inicia con los bytes 3C 3F 78 6D 6C (es decir, los caracteres ASCII "encoding=. Si está presente, a continuación, utilizar el que codifica. Si está ausente, entonces asumir UTF-8, que es la codificación XML por defecto.

Si necesita apoyar EBCDIC, también buscan la secuencia equivalente 4C 6F A7 94 93.

En general, si usted tiene un formato de archivo que contiene una declaración de codificación, y luego buscar que la declaración en lugar de tratar de adivinar la codificación.

Ninguno de los anteriores

Hay cientos de otras codificaciones, que requieren más esfuerzo por detectar. Recomiendo probar detector de conjunto de caracteres de Mozilla o un puerto .NET de ella .

Un defecto razonable

Si ha descartado las codificaciones UTF, y no tiene una declaración de codificación o la detección estadística que apunta a una codificación diferente, asumen ISO-8859-1 o el estrechamente relacionado Windows-1252 . (Tenga en cuenta que el último estándar HTML requiere una declaración “ISO-8859-1” debe interpretarse como Windows-1252.) Página de códigos predeterminada Ser Windows para Inglés (y otros lenguajes populares como español, portugués , alemán y francés), es el más comúnmente encontrado codificación que no sea UTF-8.

Otros consejos

Si quiere buscar una solución "simple", es posible encontrar esta clase que arme útil:

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

Se hace la detección BOM automáticamente primero, y luego trata de diferenciar entre codificaciones Unicode sin BOM, vs alguna otra codificación predeterminada (generalmente de Windows-1252, incorrectamente etiquetado como Encoding.ASCII en .Net).

Como se señaló anteriormente, una solución "más pesado" que implica NCharDet o MLang puede ser más apropiado, y como nota en la página de información general de esta clase, el mejor es el de proporcionar algún tipo de interactividad con el usuario, si es posible, porque simplemente no hay 100% de tasa de detección posible!

Uso StreamReader y dirigirla para detectar la codificación para usted:

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

Y el uso página de códigos identificadores https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756 (v = vs.85) .aspx con el fin de lógica de conmutación en función de la misma.

Varias respuestas están aquí pero nadie ha publicado código útil.

Aquí está mi código que detecta todas las codificaciones que Microsoft detecta en el marco de las 4 de la clase StreamReader.

Es evidente que hay que llamar a esta función inmediatamente después de abrir la corriente antes de leer cualquier otra cosa de la corriente debido a que la lista de materiales son los primeros bytes de la corriente.

Esta función requiere una corriente que puede buscar (por ejemplo, un FileStream). Si usted tiene un arroyo que no puede buscar usted debe escribir un código más complicado que devuelve un búfer de bytes con los bytes que ya se han leído, pero que no son la lista de materiales.

/// <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;
}

Si el archivo se inicia con los bytes 60, 118, 56, 46 y 49, entonces usted tiene un caso ambiguo. Podría ser UTF-8 (sin BOM) o cualquiera de las codificaciones de un solo byte como ASCII, ANSI, ISO-8859-1 etc.

Ude que es un puerto # C de Mozilla detector de juego de caracteres universal. Es fácil de usar y da muy buenos resultados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top