Maison >développement back-end >Tutoriel C#.Net >Exemple de tutoriel sur la lecture correcte des fichiers codés en chinois dans .NET (C#)

Exemple de tutoriel sur la lecture correcte des fichiers codés en chinois dans .NET (C#)

Y2J
Y2Joriginal
2017-04-24 16:56:052169parcourir

Tout d'abord, si le lecteur n'est pas familier avec l'encodage ou la BOM, il est recommandé de lire d'abord cet article : .NET (C#) : Character Encoding (Encoding) et Byte Order Mark (BOM).
Le codage chinois peut essentiellement être divisé en deux catégories :
1. Un ensemble étendu de codage ANSI : tel que GBK, GB2312, GB18030, etc. Il n'existe pas de nomenclature pour ce type de codage (certains codages chinois standard plus récents , tels que les encodages GB18030 et GBK, tous sont rétrocompatibles avec l'encodage GB2312).
2. Ensemble d'encodage Unicode : tel que UTF-8, UTF-16, UTF-32, etc. Ce type de codage peut avoir une nomenclature ou non.
3. Certains encodages Unicode ont également des problèmes d'ordre d'octets spécifiques (Endianess), qui sont ce qu'on appelle Little endian et Big endian. Différents ordres de section correspondent à différentes nomenclatures, comme UTF16, mais UTF8 n'a pas de problèmes d'ordre d'octet. .

OK, après avoir compris les connaissances de base, revenons au sujet, comment ouvrir correctement les fichiers texte chinois. La première information à confirmer est la suivante : votre fichier codé Unicode contient-il une nomenclature ?

Si la nomenclature est incluse, alors tout est facile à dire ! Car si nous trouvons la nomenclature, nous connaîtrons son encodage spécifique. Si la nomenclature n'est pas trouvée, ce n'est pas Unicode. Nous pouvons ouvrir le fichier texte en utilisant le jeu de codage chinois étendu ANSI par défaut du système et tout ira bien.
Et si l'encodage Unicode n'a pas de nomenclature (évidemment, vous ne pouvez pas garantir que tous les fichiers Unicode qui vous sont fournis par les utilisateurs ont une nomenclature), alors vous devez déterminer manuellement s'il s'agit de GBK à partir des octets d'origine ? Ou UTF8 ? Ou un autre encodage ? . Cela nécessite un algorithme de détection d'encodage spécifique (vous pouvez rechercher sur Google "jeu de caractères | détection d'encodage"). Bien sûr, l'algorithme de détection d'encodage peut ne pas être précis à 100 %. C'est précisément à cause de cela que le Bloc-notes de Windows a caché le bug des faits. Lorsque vous naviguez sur le Web dans Chrome, vous rencontrerez également des caractères tronqués. Personnellement, je pense que la connaissance du codage de Notepad++ est assez précise.
Il existe de nombreux algorithmes de sensibilisation au codage, comme ce projet : https://code.google.com/p/ude


Si Unicode est fourni avec la nomenclature, il n'est pas nécessaire de recourir à des tiers. bibliothèques du parti. Cependant, certaines choses doivent être expliquées.

Le problème est que les méthodes de lecture de texte (classe File et StreamReader) dans .NET lisent en codage UTF8 par défaut, donc ces fichiers texte GBK sont ouverts directement avec .NET (si aucun encodage n'est spécifié). ça doit être du charabia !

Tout d'abord, la solution la plus efficace ici consiste à utiliser le codage étendu ANSI par défaut du système, qui est le codage non Unicode par défaut du système pour lire le code de référence :

//输出系统默认非Unicode编码Console.WriteLine(Encoding.Default.EncodingName);//使用系统默认非Unicode编码来打开文件var fileContent = File.ReadAllText("C:\test.txt", Encoding.Default);

. en chinois simplifié Le système Windows devrait afficher :

Chinois simplifié (GB2312)2fdd645cb9bdac4e94e371c5af0fec45...

Et l'utilisation de cette méthode ne se limite pas au chinois simplifié.

Bien sûr, vous pouvez également spécifier manuellement un encodage, tel que l'encodage GBK. Mais si vous utilisez l'encodage GBK spécifié pour ouvrir un fichier Unicode, le fichier sera-t-il toujours ouvert avec succès ? La réponse est toujours réussie. La raison en est que .NET détectera automatiquement la nomenclature par défaut lors de l'ouverture d'un fichier et utilisera l'encodage obtenu sur la base de la nomenclature pour ouvrir le fichier. S'il n'y a pas de nomenclature, le fichier sera ouvert avec la zone d'encodage spécifiée par l'utilisateur. . Si l'utilisateur ne précise pas l'encodage, l'encodage UTF8 sera utilisé.

Ce paramètre "Détection automatique de nomenclature" peut être défini dans le constructeur de StreamReader, correspondant au paramètre detectEncodingFromByteOrderMarks.

Mais il ne peut pas être défini dans la méthode correspondante de la classe File. (Par exemple : Fichier.ReadAllText).

Par exemple, le code suivant utilise :

Encodage GB2312, détectant automatiquement la nomenclature pour lire le texte GB2312

Encodage GB2312, détectant automatiquement la nomenclature pour lire le texte Unicode

Encodage GB2312, lecture du texte Unicode sans remarquer la nomenclature

static void Main(){    var gb2312 = Encoding.GetEncoding("GB2312");    //用GB2312编码,自动觉察BOM 来读取GB2312文本    ReadFile("gbk.txt", gb2312, true);    //用GB2312编码,自动觉察BOM 来读取Unicode文本    ReadFile("unicode.txt", gb2312, true);    //用GB2312编码,不觉察BOM 来读取Unicode文本    ReadFile("unicode.txt", gb2312, false);}//通过StreamReader读取文本 static void ReadFile(string path, Encoding enc, bool detectEncodingFromByteOrderMarks){    StreamReader sr;    using (sr = new StreamReader(path, enc, detectEncodingFromByteOrderMarks))    {        Console.WriteLine(sr.ReadToEnd());    }}

Sortie :

a刘a刘???

La troisième ligne est tronquée.

Comme vous pouvez le voir ci-dessus, l'utilisation de l'encodage GB2312 pour ouvrir des fichiers Unicode sera également efficace. Étant donné que le paramètre « Détecter automatiquement la nomenclature » ​​est True, lorsqu'il s'avère que le fichier a une nomenclature, .NET détectera qu'il s'agit d'un fichier Unicode via la nomenclature, puis utilisera Unicode pour ouvrir le fichier. Bien entendu, s'il n'y a pas de nomenclature, les paramètres d'encodage spécifiés seront utilisés pour ouvrir le fichier. Pour le texte codé GB2312, il n'y a évidemment pas de nomenclature, donc l'encodage GB2312 doit être spécifié, sinon .NET utilisera l'encodage UTF8 par défaut pour analyser le fichier et le résultat ne sera pas lu. Les caractères tronqués dans la troisième ligne sont dus au fait que "Détection automatique de la nomenclature" est fausse. .NET utilisera directement le codage GB2312 spécifié pour lire un fichier texte codé Unicode avec la nomenclature, ce qui ne peut évidemment pas réussir.

Bien sûr, vous pouvez également déterminer vous-même la nomenclature. S'il n'y a pas de nomenclature, spécifiez un encodage par défaut pour ouvrir le texte. J'en ai parlé dans un article précédent (.NET (C#) : Détection d'encodage à partir de fichiers).

Code :

static void Main(){    PrintText("gb2312.txt");    PrintText("unicode.txt");}//根据文件自动觉察编码并输出内容static void PrintText(string path){    var enc = GetEncoding(path, Encoding.GetEncoding("GB2312"));    using (var sr = new StreamReader(path, enc))    {        Console.WriteLine(sr.ReadToEnd());    }}/// <summary>/// 根据文件尝试返回字符编码/// </summary>/// <param name="file">文件路径</param>/// <param name="defEnc">没有BOM返回的默认编码</param>/// <returns>如果文件无法读取,返回null。否则,返回根据BOM判断的编码或者缺省编码(没有BOM)。</returns>static Encoding GetEncoding(string file, Encoding defEnc){    using (var stream = File.OpenRead(file))    {        //判断流可读?        if (!stream.CanRead)            return null;        //字节数组存储BOM        var bom = new byte[4];        //实际读入的长度        int readc;        readc = stream.Read(bom, 0, 4);        if (readc >= 2)        {            if (readc >= 4)            {                //UTF32,Big-Endian                if (CheckBytes(bom, 4, 0x00, 0x00, 0xFE, 0xFF))                    return new UTF32Encoding(true, true);                //UTF32,Little-Endian                if (CheckBytes(bom, 4, 0xFF, 0xFE, 0x00, 0x00))                    return new UTF32Encoding(false, true);            }            //UTF8            if (readc >= 3 && CheckBytes(bom, 3, 0xEF, 0xBB, 0xBF))                return new UTF8Encoding(true);            //UTF16,Big-Endian            if (CheckBytes(bom, 2, 0xFE, 0xFF))                return new UnicodeEncoding(true, true);            //UTF16,Little-Endian            if (CheckBytes(bom, 2, 0xFF, 0xFE))                return new UnicodeEncoding(false, true);        }        return defEnc;    }}//辅助函数,判断字节中的值static bool CheckBytes(byte[] bytes, int count, params int[] values){    for (int i = 0; i < count; i++)        if (bytes[i] != values[i])            return false;    return true;}

Dans le code ci-dessus, pour le texte Unicode, la méthode GetEncoding renverra l'encodage UTF16 (plus précisément : elle renverra également l'encodage UTF16 Big ou Little-Endian selon BOM) et les fichiers sans BOM renverront le codage GB2312 par défaut.

Articles associés :

.NET(C#) : Détecter l'encodage des fichiers

.NET(C#) : Encodage des caractères (Encodage) et marque d'ordre des octets (BOM) )

.NET(C#) : utilisez la classe System.Text.Decoder pour traiter le « flux de texte »

.NET(C#) : une brève discussion sur les ressources du manifeste d'assembly et les ressources RESX

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn