80 votes

Comment détecter le codage des caractères d'un fichier texte ?

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

J'essaie avec ce code d'obtenir l'encodage 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;
    }

Mes cinq premiers octets sont 60, 118, 56, 46 et 49.

Existe-t-il un tableau qui montre quel encodage correspond à ces cinq premiers octets ?

4 votes

La marque d'ordre des octets ne doit pas être utilisée pour détecter les codages. Il y a des cas où il est ambigu de savoir quel encodage est utilisé : UTF-16 LE et UTF-32 LE commencent tous deux par les deux mêmes octets. La BOM ne devrait être utilisée que pour détecter l'ordre des octets (d'où son nom). De plus, l'UTF-8 ne devrait pas, à proprement parler, avoir de marque d'ordre des octets et en ajouter une peut interférer avec certains logiciels qui ne l'attendent pas.

0 votes

@Mark Bayers, y a-t-il un moyen de savoir quel encodage est utilisé dans mon fichier ?

5 votes

@Mark Byers : UTF-32 LE commence avec les mêmes 2 octets que UTF-16 LE. Cependant, il suit également avec les octets 00 00 ce qui est (je pense très) improbable dans UTF-16 LE. De plus, la BOM en théorie devrait indiquer ce que vous dites, mais en pratique, elle agit comme une signature pour montrer quel est l'encodage. Voir : unicode.org/faq/utf_bom.html#bom4

90voto

dan04 Points 33306

Vous ne pouvez pas compter sur le fait que le fichier ait une nomenclature. L'UTF-8 ne l'exige pas. Et les encodages non-Unicode n'ont même pas de BOM. Il existe cependant d'autres moyens de détecter l'encodage.

UTF-32

La nomenclature est 00 00 FE FF (pour BE) ou FF FE 00 00 (pour LE).

Mais l'UTF-32 est facile à détecter, même sans nomenclature. En effet, la plage de points de code Unicode est limitée à U+10FFFF, et donc les unités UTF-32 ont toujours le motif 00 {0x|10} xx xx (pour BE) ou xx xx {0x|10} 00 (pour LE). Si les données ont une longueur qui est un multiple de 4, et suivent l'un de ces modèles, vous pouvez supposer sans risque qu'il s'agit d'UTF-32. Les faux positifs sont presque impossibles en raison de la rareté des octets 00 dans les codages orientés octet.

US-ASCII

Pas de nomenclature, mais vous n'en avez pas besoin. L'ASCII est facilement identifiable par l'absence d'octets dans la plage 80-FF.

UTF-8

La nomenclature est EF BB BF. Mais vous ne pouvez pas vous fier à cela. De nombreux fichiers UTF-8 n'ont pas de BOM, surtout s'ils proviennent de systèmes non-Windows.

Mais vous pouvez supposer sans risque que si un fichier est validé comme UTF-8, c'est que est UTF-8. Les faux positifs sont rares.

Plus précisément, étant donné que les données ne sont pas ASCII, le taux de faux positifs pour une séquence de 2 octets n'est que 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

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

Il peut exister des fichiers UTF-16 sans BOM, mais il serait très difficile de les détecter. La seule façon fiable de reconnaître un UTF-16 sans BOM est de rechercher des paires de substituts (D[8-B]xx D[C-F]xx), mais les caractères non BMP sont trop rarement utilisés pour que cette approche soit pratique.

XML

Si votre fichier commence par les octets 3C 3F 78 6D 6C (c'est-à-dire les caractères ASCII "<?xml"), recherchez une balise encoding= déclaration. S'il est présent, il faut utiliser cet encodage. S'il n'y en a pas, il s'agit de l'encodage UTF-8, qui est l'encodage XML par défaut.

Si vous devez prendre en charge l'EBCDIC, recherchez également la séquence équivalente 4C 6F A7 94 93.

En général, si un format de fichier contient une déclaration d'encodage, recherchez cette déclaration plutôt que d'essayer de deviner l'encodage.

Aucune de ces réponses

Il existe des centaines d'autres encodages, dont la détection demande plus d'efforts. Je recommande d'essayer Le détecteur d'encodage de Mozilla ou un portage .NET de celui-ci .

0 votes

Pouvez-vous clarifier votre analyse de l'UTF-8 ci-dessus ? Je pense que vous dites que si vous avez un fichier au hasard [Si la distribution des caractères à partir desquels le fichier est constitué est plate, les risques de confusion sont faibles. En pratique, aucun fichier texte n'a une distribution plate comme celle-ci... donc je m'attendrais à un impact sévère sur l'analyse avec un taux de faux positifs beaucoup plus élevé. Comment pouvez-vous distinguer entre UTF-16 et UTF-8 si les fichiers ont un nombre pair d'octets ?

0 votes

Oui, c'est pour une distribution aléatoire d'octets. Pour des données réelles, c'est plus difficile à calculer. Mais le fait est que, pour qu'un fichier codé (par exemple, Windows-1252) soit mal interprété comme étant UTF-8, il devrait contenir des séquences de caractères bizarres telles que ’ .

1 votes

OK, ce que j'attendais. Pouvez-vous aborder la question de la distinction entre UTF-8 et UTF-16 ? PS : Merci pour cette réponse très utile. +1

13voto

Tao Points 5475

Si vous souhaitez rechercher une solution "simple", ce cours que j'ai mis sur pied pourrait vous être utile :

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

Il commence par détecter automatiquement la BOM, puis tente de faire la différence entre les encodages Unicode sans BOM et un autre encodage par défaut (généralement Windows-1252, incorrectement appelé Encoding.ASCII dans .Net).

Comme indiqué ci-dessus, une solution plus "lourde" impliquant NCharDet ou MLang peut être plus appropriée, et comme je le note sur la page d'aperçu de cette classe, le mieux est de fournir une certaine forme d'interactivité avec l'utilisateur si possible, car il n'y a tout simplement pas de taux de détection de 100% possible !

1 votes

En fait, Encoding.GetEncoding("Windows-1252") donne une classe d'objets différente de Encoding.ASCII . Pendant le débogage, Windows-1252 apparaît comme une System.Text.SBCSCodePageEncoding alors que ascii est un objet System.Text.ASCIIEncoding objet. Je n'utilise jamais l'ASCII quand j'ai besoin de Windows-1252.

0 votes

Pour faire correspondre des expressions régulières à des données binaires (octets), la méthode correcte est la suivante : string data = Encoding.GetEncoding("iso-8859-1").GetString(bytes); Parce qu'il s'agit du seul codage à octet unique qui offre une correspondance d'octet à octet à chaîne.

7voto

Phil Hunt Points 5153

Utilisez StreamReader et lui demander de détecter l'encodage pour vous :

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

4 votes

Ne fonctionne pas, le StreamReader suppose que votre fichier est en UTF-8.

0 votes

@Cedric : Check MSDN pour ce constructeur. Avez-vous des preuves que le constructeur ne fonctionne pas en accord avec la documentation ? Je vous l'accorde, c'est possible dans la documentation de Microsoft :-)

0 votes

Désolé, vous avez raison. Mais ça ne marche pas :-( l'encodage n'est pas bon.

2voto

Jon Points 194296

1voto

Steven K. Points 1714

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X