Question

J'essaie de détecter le codage de caractères est utilisé dans mon dossier.

J'essaie avec ce code pour obtenir le codage standard

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

My cinq octets premier sont 60, 118, 56, 46 et 49.

Y at-il un tableau qui montre que le codage correspond à ces cinq premiers octets?

Était-ce utile?

La solution

Vous ne pouvez pas dépendre du fichier ayant une nomenclature. UTF-8 ne l'exige pas. Et encodages non-Unicode ne sont même pas une nomenclature. Il y a, cependant, d'autres façons de détecter le codage.

UTF-32

BOM est 00 00 FE FF (pour BE) ou FF FE 00 00 (pour LE).

Mais UTF-32 est facile à détecter, même sans une nomenclature. En effet, la plage de point de code Unicode est limité à U + 10FFFF, et donc UTF-32 unités ont toujours le modèle 00 {00-10} xx xx (pour BE) ou xx xx {00-10} 00 (pour LE) . Si les données ont une longueur qui est un multiple de 4, et suit l'un de ces modèles, vous pouvez supposer en toute sécurité UTF-32. Les faux positifs sont presque impossible en raison de la rareté des 00 octets codages par octets.

US-ASCII

Pas de nomenclature, mais vous ne pas besoin. ASCII peut être facilement identifié par le manque d'octets dans la gamme de 80 FF.

UTF-8

BOM est EF BB BF. Mais vous ne pouvez pas compter sur ce point. Beaucoup de fichiers UTF-8 ne sont pas une nomenclature, surtout si elles proviennent des systèmes non-Windows.

Mais vous pouvez supposer que si un fichier est validée UTF-8, il UTF-8. Les faux positifs sont rares.

En particulier, étant donné que les données ne sont pas ASCII, le taux de faux positifs pour une séquence de 2 octets est seulement de 3,9% (1920/49152). Pour une séquence de 7 octets, il est inférieur à 1%. Pour une séquence de 12 octets, il est inférieur à 0,1%. Pour une séquence de 24 octets, il est inférieur à 1 sur un million.

UTF-16

BOM est FE FF (pour BE) ou FF FE (pour LE). Notez que l'UTF-16LE nomenclature se trouve au début de l'UTF-32LE nomenclature, afin de vérifier UTF-32 d'abord.

Si vous arrive d'avoir un fichier qui se compose principalement de caractères ISO-8859-1, ayant la moitié des octets de fichier de 00 soit serait également un bon indicateur de UTF-16.

Dans le cas contraire, le seul moyen fiable de reconnaître UTF-16 sans une nomenclature est de rechercher des paires de substitution (D [8-B] xx D [CF] xx), mais les caractères non-BMP sont trop rarement utilisés pour faire cette approche pratique.

XML

Si votre fichier commence par les octets 3C 3F 78 6D 6C (à savoir, les caractères ASCII "encoding=. Le cas échéant, utilisez ce codage. En cas d'absence, puis prendre UTF-8, qui est l'encodage XML par défaut.

Si vous avez besoin pour soutenir EBCDIC, regardez également pour la séquence équivalente 4C 6F A7 94 93.

En général, si vous avez un format de fichier qui contient une déclaration de codage, puis pour regarder cette déclaration plutôt que d'essayer de deviner l'encodage.

Aucune de ces

Il y a des centaines d'autres encodages, qui nécessitent plus d'efforts pour détecter. Je recommande d'essayer détecteur de charset de Mozilla ou un port .NET de celui-ci .

Un défaut raisonnable

Si vous avez exclu les encodages UTF, et ne dispose pas d'une déclaration de codage ou de détection statistique qui pointe vers un codage différent, supposons ISO-8859-1 ou étroitement lié Windows 1252 . (Notez que la dernière norme HTML nécessite une « ISO-8859-1 » déclaration à être interprété comme Windows 1252.) Page de code par défaut être Windows pour l'anglais (et d'autres langues populaires comme espagnol, portugais , allemand et français), il est l'encodage autre que UTF-8 le plus souvent rencontré.

Autres conseils

Si vous souhaitez poursuivre une solution « simple », vous trouverez peut-être cette classe je mets ensemble utile:

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

Il fait la détection de la nomenclature automatiquement d'abord, et essaie ensuite de faire la différence entre les encodages Unicode sans nomenclature, contre un autre encodage par défaut (généralement Windows 1252, incorrectement étiquetés comme Encoding.ASCII en .Net).

Comme indiqué ci-dessus, une solution « plus lourd » impliquant NCharDet ou MLang peut être plus approprié, et que je note sur la page de présentation de cette classe, le meilleur est de fournir une certaine forme d'interactivité avec l'utilisateur, si possible, parce qu'il n'y a tout simplement pas de taux de détection de 100%! possible

Utilisez StreamReader et directe pour détecter l'encodage pour vous:

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

utilisation Code Page Identifiers https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756 (v = vs.85) .aspx afin de logique de commutation en fonction de cela.

Plusieurs réponses sont ici, mais personne n'a posté le code utile.

Voici mon code qui détecte tous les encodages que Microsoft détecte dans cadre 4 dans la classe StreamReader.

Il est évident que vous devez appeler cette fonction immédiatement après l'ouverture du flux avant de lire quoi que ce soit d'autre à partir du flux parce que la nomenclature sont les premiers octets dans le flux.

Cette fonction nécessite un flux qui peut demander (par exemple un FileStream). Si vous avez un flux qui ne peut pas chercher, vous devez écrire un code plus compliqué que renvoie un tampon d'octets avec les octets qui ont déjà été lus, mais qui ne sont pas de nomenclature.

/// <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 votre fichier commence par les octets 60, 118, 56, 46 et 49, alors vous avez un cas ambigu. Il pourrait être UTF-8 (sans BOM) ou l'un des encodages mono-octet comme ASCII, ANSI, ISO-8859-1 etc.

J'utilise Ude qui est un port C # de Mozilla Universal Charset détecteur. Il est facile à utiliser et donne des résultats vraiment bons.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top