Déterminer le codage d'une chaîne en C #

127

Existe-t-il un moyen de déterminer le codage d'une chaîne en C #?

Dites, j'ai une chaîne de nom de fichier, mais je ne sais pas si elle est encodée en Unicode UTF-16 ou l'encodage par défaut du système, comment puis-je le savoir?

krebstar
la source
Vous ne pouvez pas «encoder» en Unicode. Et il n'y a aucun moyen de déterminer automatiquement le codage d' une chaîne donnée, sans aucune autre information préalable.
Nicolas Dumazet
5
pour être plus clair peut-être: vous encodez des points de code Unicode en chaînes d'octets d'un jeu de caractères en utilisant un schéma de "codage" (utf- , iso- , big5, shift-jis, etc ...), et vous décodez des chaînes d'octets à partir d'un jeu de caractères sur Unicode. Vous n'encodez pas les chaînes d'octets en Unicode. Vous ne décodez pas l'Unicode en bytestrings.
Nicolas Dumazet
13
@NicDunZ - l'encodage lui-même (en particulier UTF-16) est aussi communément appelé "Unicode". Vrai ou faux, c'est la vie. Même dans .NET, regardez Encoding.Unicode - ce qui signifie UTF-16.
Marc Gravell
2
eh bien, je ne savais pas que .NET était si trompeur. Cela ressemble à une terrible habitude à apprendre. Et désolé @krebstar, ce n'était pas mon intention (je pense toujours que votre question éditée a beaucoup plus de sens maintenant qu'avant)
Nicolas Dumazet
1
@Nicdumz # 1: Il existe un moyen de déterminer de manière probabiliste quel encodage utiliser. Regardez ce que fait IE (et maintenant aussi FF avec View - Encodage de caractères - Détection automatique) pour cela: il essaie un encodage et voit s'il est peut-être "bien écrit <mettez un nom de langue ici>" ou changez-le et réessaye . Allez, ça peut être amusant!
SnippyHolloW

Réponses:

31

Découvrez Utf8Checker, c'est une classe simple qui fait exactement cela en code managé pur. http://utf8checker.codeplex.com

Remarque: comme déjà indiqué, "déterminer l'encodage" n'a de sens que pour les flux d'octets. Si vous avez une chaîne, elle est déjà encodée par quelqu'un en cours de route qui connaissait déjà ou a deviné l'encodage pour obtenir la chaîne en premier lieu.

devdimi
la source
Si la chaîne est un décodage incorrect effectué avec un encodage simplement 8 bits et que l'encodage est utilisé pour le décoder, vous pouvez généralement récupérer les octets sans aucune corruption.
Nyerguds
57

Le code ci-dessous présente les caractéristiques suivantes:

  1. Détection ou tentative de détection de UTF-7, UTF-8/16/32 (bom, no bom, little & big endian)
  2. Retombe à la page de codes par défaut locale si aucun encodage Unicode n'a été trouvé.
  3. Détecte (avec une forte probabilité) les fichiers Unicode avec la nomenclature / signature manquante
  4. Recherche charset = xyz et encoding = xyz dans le fichier pour aider à déterminer l'encodage.
  5. Pour enregistrer le traitement, vous pouvez «goûter» le fichier (nombre d'octets définissable).
  6. Le fichier texte de codage et décodé est renvoyé.
  7. Solution purement basée sur l'octet pour l'efficacité

Comme d'autres l'ont dit, aucune solution ne peut être parfaite (et on ne peut certainement pas faire la différence entre les différents encodages ASCII étendus 8 bits utilisés dans le monde), mais nous pouvons être `` assez bons '' surtout si le développeur présente également à l'utilisateur une liste d'encodages alternatifs comme indiqué ici: Quel est l'encodage le plus courant de chaque langue?

Une liste complète des encodages peut être trouvée en utilisant Encoding.GetEncodings();

// Function to detect the encoding for UTF-7, UTF-8/16/32 (bom, no bom, little
// & big endian), and local default codepage, and potentially other codepages.
// 'taster' = number of bytes to check of the file (to save processing). Higher
// value is slower, but more reliable (especially UTF-8 with special characters
// later on may appear to be ASCII initially). If taster = 0, then taster
// becomes the length of the file (for maximum reliability). 'text' is simply
// the string with the discovered encoding applied to the file.
public Encoding detectTextEncoding(string filename, out String text, int taster = 1000)
{
    byte[] b = File.ReadAllBytes(filename);

    //////////////// First check the low hanging fruit by checking if a
    //////////////// BOM/signature exists (sourced from http://www.unicode.org/faq/utf_bom.html#bom4)
    if (b.Length >= 4 && b[0] == 0x00 && b[1] == 0x00 && b[2] == 0xFE && b[3] == 0xFF) { text = Encoding.GetEncoding("utf-32BE").GetString(b, 4, b.Length - 4); return Encoding.GetEncoding("utf-32BE"); }  // UTF-32, big-endian 
    else if (b.Length >= 4 && b[0] == 0xFF && b[1] == 0xFE && b[2] == 0x00 && b[3] == 0x00) { text = Encoding.UTF32.GetString(b, 4, b.Length - 4); return Encoding.UTF32; }    // UTF-32, little-endian
    else if (b.Length >= 2 && b[0] == 0xFE && b[1] == 0xFF) { text = Encoding.BigEndianUnicode.GetString(b, 2, b.Length - 2); return Encoding.BigEndianUnicode; }     // UTF-16, big-endian
    else if (b.Length >= 2 && b[0] == 0xFF && b[1] == 0xFE) { text = Encoding.Unicode.GetString(b, 2, b.Length - 2); return Encoding.Unicode; }              // UTF-16, little-endian
    else if (b.Length >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF) { text = Encoding.UTF8.GetString(b, 3, b.Length - 3); return Encoding.UTF8; } // UTF-8
    else if (b.Length >= 3 && b[0] == 0x2b && b[1] == 0x2f && b[2] == 0x76) { text = Encoding.UTF7.GetString(b,3,b.Length-3); return Encoding.UTF7; } // UTF-7


    //////////// If the code reaches here, no BOM/signature was found, so now
    //////////// we need to 'taste' the file to see if can manually discover
    //////////// the encoding. A high taster value is desired for UTF-8
    if (taster == 0 || taster > b.Length) taster = b.Length;    // Taster size can't be bigger than the filesize obviously.


    // Some text files are encoded in UTF8, but have no BOM/signature. Hence
    // the below manually checks for a UTF8 pattern. This code is based off
    // the top answer at: /programming/6555015/check-for-invalid-utf8
    // For our purposes, an unnecessarily strict (and terser/slower)
    // implementation is shown at: /programming/1031645/how-to-detect-utf-8-in-plain-c
    // For the below, false positives should be exceedingly rare (and would
    // be either slightly malformed UTF-8 (which would suit our purposes
    // anyway) or 8-bit extended ASCII/UTF-16/32 at a vanishingly long shot).
    int i = 0;
    bool utf8 = false;
    while (i < taster - 4)
    {
        if (b[i] <= 0x7F) { i += 1; continue; }     // If all characters are below 0x80, then it is valid UTF8, but UTF8 is not 'required' (and therefore the text is more desirable to be treated as the default codepage of the computer). Hence, there's no "utf8 = true;" code unlike the next three checks.
        if (b[i] >= 0xC2 && b[i] <= 0xDF && b[i + 1] >= 0x80 && b[i + 1] < 0xC0) { i += 2; utf8 = true; continue; }
        if (b[i] >= 0xE0 && b[i] <= 0xF0 && b[i + 1] >= 0x80 && b[i + 1] < 0xC0 && b[i + 2] >= 0x80 && b[i + 2] < 0xC0) { i += 3; utf8 = true; continue; }
        if (b[i] >= 0xF0 && b[i] <= 0xF4 && b[i + 1] >= 0x80 && b[i + 1] < 0xC0 && b[i + 2] >= 0x80 && b[i + 2] < 0xC0 && b[i + 3] >= 0x80 && b[i + 3] < 0xC0) { i += 4; utf8 = true; continue; }
        utf8 = false; break;
    }
    if (utf8 == true) {
        text = Encoding.UTF8.GetString(b);
        return Encoding.UTF8;
    }


    // The next check is a heuristic attempt to detect UTF-16 without a BOM.
    // We simply look for zeroes in odd or even byte places, and if a certain
    // threshold is reached, the code is 'probably' UF-16.          
    double threshold = 0.1; // proportion of chars step 2 which must be zeroed to be diagnosed as utf-16. 0.1 = 10%
    int count = 0;
    for (int n = 0; n < taster; n += 2) if (b[n] == 0) count++;
    if (((double)count) / taster > threshold) { text = Encoding.BigEndianUnicode.GetString(b); return Encoding.BigEndianUnicode; }
    count = 0;
    for (int n = 1; n < taster; n += 2) if (b[n] == 0) count++;
    if (((double)count) / taster > threshold) { text = Encoding.Unicode.GetString(b); return Encoding.Unicode; } // (little-endian)


    // Finally, a long shot - let's see if we can find "charset=xyz" or
    // "encoding=xyz" to identify the encoding:
    for (int n = 0; n < taster-9; n++)
    {
        if (
            ((b[n + 0] == 'c' || b[n + 0] == 'C') && (b[n + 1] == 'h' || b[n + 1] == 'H') && (b[n + 2] == 'a' || b[n + 2] == 'A') && (b[n + 3] == 'r' || b[n + 3] == 'R') && (b[n + 4] == 's' || b[n + 4] == 'S') && (b[n + 5] == 'e' || b[n + 5] == 'E') && (b[n + 6] == 't' || b[n + 6] == 'T') && (b[n + 7] == '=')) ||
            ((b[n + 0] == 'e' || b[n + 0] == 'E') && (b[n + 1] == 'n' || b[n + 1] == 'N') && (b[n + 2] == 'c' || b[n + 2] == 'C') && (b[n + 3] == 'o' || b[n + 3] == 'O') && (b[n + 4] == 'd' || b[n + 4] == 'D') && (b[n + 5] == 'i' || b[n + 5] == 'I') && (b[n + 6] == 'n' || b[n + 6] == 'N') && (b[n + 7] == 'g' || b[n + 7] == 'G') && (b[n + 8] == '='))
            )
        {
            if (b[n + 0] == 'c' || b[n + 0] == 'C') n += 8; else n += 9;
            if (b[n] == '"' || b[n] == '\'') n++;
            int oldn = n;
            while (n < taster && (b[n] == '_' || b[n] == '-' || (b[n] >= '0' && b[n] <= '9') || (b[n] >= 'a' && b[n] <= 'z') || (b[n] >= 'A' && b[n] <= 'Z')))
            { n++; }
            byte[] nb = new byte[n-oldn];
            Array.Copy(b, oldn, nb, 0, n-oldn);
            try {
                string internalEnc = Encoding.ASCII.GetString(nb);
                text = Encoding.GetEncoding(internalEnc).GetString(b);
                return Encoding.GetEncoding(internalEnc);
            }
            catch { break; }    // If C# doesn't recognize the name of the encoding, break.
        }
    }


    // If all else fails, the encoding is probably (though certainly not
    // definitely) the user's local codepage! One might present to the user a
    // list of alternative encodings as shown here: /programming/8509339/what-is-the-most-common-encoding-of-each-language
    // A full list can be found using Encoding.GetEncodings();
    text = Encoding.Default.GetString(b);
    return Encoding.Default;
}
Dan W
la source
Cela fonctionne pour les fichiers cyrilliques (et probablement tous les autres) .eml (à partir de l'en-tête du jeu de caractères du courrier)
Nime Cloud
UTF-7 ne peut pas être décodé aussi naïvement, en fait; son préambule complet est plus long et comprend deux bits du premier caractère. Le système .Net semble n'avoir aucun support pour le système de préambule de UTF7.
Nyerguds
A travaillé pour moi quand aucune des autres méthodes que j'ai vérifiées n'a aidé! Merci Dan.
Tejasvi Hegde
Merci pour votre solution. Je l'utilise pour déterminer l'encodage de fichiers provenant de sources complètement différentes. Ce que j'ai trouvé cependant, c'est que si j'utilise une valeur de dégustation trop faible, le résultat peut être faux. (par exemple, le code renvoyait Encoding.Default pour un fichier UTF8, même si j'utilisais b.Length / 10 comme dégustateur.) Alors je me suis demandé quel était l'argument pour utiliser un dégustateur inférieur à b.Length? Il semble que je ne puisse conclure que Encoding.Default est acceptable si et seulement si j'ai scanné tout le fichier.
Sean
@Sean: C'est pour quand la vitesse compte plus que la précision, en particulier pour les fichiers qui peuvent atteindre des dizaines ou des centaines de mégaoctets. D'après mon expérience, même une faible valeur de dégustation peut donner des résultats corrects ~ 99,9% du temps. Votre expérience peut différer.
Dan W
33

Cela dépend d'où la chaîne «vient». Une chaîne .NET est Unicode (UTF-16). La seule façon dont cela pourrait être différent si, par exemple, vous lisiez les données d'une base de données dans un tableau d'octets.

Cet article CodeProject peut être intéressant: Détecter l'encodage pour le texte entrant et sortant

Les chaînes de Jon Skeet en C # et .NET sont une excellente explication des chaînes .NET.

Blé Mitch
la source
Il est venu d'une application C ++ non Unicode. L'article CodeProject semble un peu trop complexe, mais il semble faire ce que je veux faire .. Merci ..
krebstar
18

Je sais que c'est un peu tard - mais pour être clair:

Une chaîne n'a pas vraiment de codage ... dans .NET, une chaîne est une collection d'objets char. Essentiellement, s'il s'agit d'une chaîne, elle a déjà été décodée.

Cependant, si vous lisez le contenu d'un fichier, qui est composé d'octets, et que vous souhaitez le convertir en chaîne, alors le codage du fichier doit être utilisé.

.NET comprend des classes d'encodage et de décodage pour: ASCII, UTF7, UTF8, UTF32 et plus.

La plupart de ces codages contiennent certaines marques d'ordre des octets qui peuvent être utilisées pour distinguer le type de codage utilisé.

La classe .NET System.IO.StreamReader est capable de déterminer le codage utilisé dans un flux, en lisant ces marques d'ordre des octets;

Voici un exemple:

    /// <summary>
    /// return the detected encoding and the contents of the file.
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="contents"></param>
    /// <returns></returns>
    public static Encoding DetectEncoding(String fileName, out String contents)
    {
        // open the file with the stream-reader:
        using (StreamReader reader = new StreamReader(fileName, true))
        {
            // read the contents of the file into a string
            contents = reader.ReadToEnd();

            // return the encoding.
            return reader.CurrentEncoding;
        }
    }
Pont Simon
la source
3
Cela ne fonctionnera pas pour détecter UTF 16 sans la nomenclature. Il ne reviendra pas non plus à la page de codes par défaut locale de l'utilisateur s'il ne détecte aucun encodage Unicode. Vous pouvez corriger ce dernier en l'ajoutant en Encoding.Defaulttant que paramètre StreamReader, mais le code ne détectera pas UTF8 sans la nomenclature.
Dan W
1
@DanW: Est-ce que UTF-16 sans BOM est déjà fait? Je n'utiliserais jamais ça; ce sera forcément un désastre d'ouvrir à peu près n'importe quoi.
Nyerguds
11

Une autre option, très tardive, désolé:

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

Cette petite classe uniquement C # utilise BOMS si elle est présente, essaie de détecter automatiquement d'éventuels codages Unicode dans le cas contraire, et revient si aucun des codages Unicode n'est possible ou probable.

Cela ressemble à UTF8Checker référencé ci-dessus fait quelque chose de similaire, mais je pense que sa portée est légèrement plus large - au lieu de juste UTF8, il vérifie également d'autres encodages Unicode possibles (UTF-16 LE ou BE) qui pourraient manquer une nomenclature.

J'espère que cela aide quelqu'un!

Tao
la source
Très joli code, il a résolu mon problème de détection d'encodage :)
CARLOS LOTH
9

Le package Nuget SimpleHelpers.FileEncoding enveloppe un port C # du détecteur de jeu de caractères universel Mozilla dans une API très simple:

var encoding = FileEncoding.DetectFileEncoding(txtFile);
Arithmomane
la source
cela devrait être plus haut, cela fournit une solution très simple: laissez les autres faire le travail: D
buddybubble
Cette bibliothèque est GPL
A br
Vraiment? Je vois une licence MIT et elle utilise un composant à triple licence (UDE), dont MPL. J'ai essayé de déterminer si UDE était problématique pour un produit propriétaire, donc si vous avez plus d'informations, ce serait grandement apprécié.
Simon Woods
5

Ma solution consiste à utiliser des éléments intégrés avec quelques solutions de secours.

J'ai choisi la stratégie d'une réponse à une autre question similaire sur stackoverflow mais je ne la trouve pas maintenant.

Il vérifie d'abord la nomenclature en utilisant la logique intégrée de StreamReader, s'il y a une nomenclature, le codage sera autre chose que Encoding.Default, et nous devons faire confiance à ce résultat.

Sinon, il vérifie si la séquence d'octets est une séquence UTF-8 valide. si c'est le cas, il devinera UTF-8 comme encodage, et sinon, encore une fois, l'encodage ASCII par défaut sera le résultat.

static Encoding getEncoding(string path) {
    var stream = new FileStream(path, FileMode.Open);
    var reader = new StreamReader(stream, Encoding.Default, true);
    reader.Read();

    if (reader.CurrentEncoding != Encoding.Default) {
        reader.Close();
        return reader.CurrentEncoding;
    }

    stream.Position = 0;

    reader = new StreamReader(stream, new UTF8Encoding(false, true));
    try {
        reader.ReadToEnd();
        reader.Close();
        return Encoding.UTF8;
    }
    catch (Exception) {
        reader.Close();
        return Encoding.Default;
    }
}
vilicvane
la source
3

Remarque: il s'agissait d'une expérience pour voir comment l'encodage UTF-8 fonctionnait en interne. La solution proposée par vilicvane , utiliser un UTF8Encodingobjet initialisé pour lever une exception en cas d'échec de décodage, est beaucoup plus simple et fait essentiellement la même chose.


J'ai écrit ce morceau de code pour différencier UTF-8 et Windows-1252. Cependant, il ne devrait pas être utilisé pour des fichiers texte gigantesques, car il charge le tout en mémoire et le scanne complètement. Je l'ai utilisé pour les fichiers de sous-titres .srt, juste pour pouvoir les sauvegarder dans l'encodage dans lequel ils étaient chargés.

Le codage donné à la fonction en tant que ref doit être le codage de secours 8 bits à utiliser au cas où le fichier serait détecté comme n'étant pas valide UTF-8; généralement, sur les systèmes Windows, ce sera Windows-1252. Cela n'a rien d'extraordinaire comme vérifier les plages ascii valides réelles, et ne détecte pas UTF-16 même sur la marque d'ordre d'octet.

La théorie derrière la détection au niveau du bit peut être trouvée ici: https://ianthehenry.com/2015/1/17/decoding-utf-8/

Fondamentalement, la plage de bits du premier octet détermine combien après il fait partie de l'entité UTF-8. Ces octets après lui sont toujours dans la même plage de bits.

/// <summary>
/// Reads a text file, and detects whether its encoding is valid UTF-8 or ascii.
/// If not, decodes the text using the given fallback encoding.
/// Bit-wise mechanism for detecting valid UTF-8 based on
/// https://ianthehenry.com/2015/1/17/decoding-utf-8/
/// </summary>
/// <param name="docBytes">The bytes read from the file.</param>
/// <param name="encoding">The default encoding to use as fallback if the text is detected not to be pure ascii or UTF-8 compliant. This ref parameter is changed to the detected encoding.</param>
/// <returns>The contents of the read file, as String.</returns>
public static String ReadFileAndGetEncoding(Byte[] docBytes, ref Encoding encoding)
{
    if (encoding == null)
        encoding = Encoding.GetEncoding(1252);
    Int32 len = docBytes.Length;
    // byte order mark for utf-8. Easiest way of detecting encoding.
    if (len > 3 && docBytes[0] == 0xEF && docBytes[1] == 0xBB && docBytes[2] == 0xBF)
    {
        encoding = new UTF8Encoding(true);
        // Note that even when initialising an encoding to have
        // a BOM, it does not cut it off the front of the input.
        return encoding.GetString(docBytes, 3, len - 3);
    }
    Boolean isPureAscii = true;
    Boolean isUtf8Valid = true;
    for (Int32 i = 0; i < len; ++i)
    {
        Int32 skip = TestUtf8(docBytes, i);
        if (skip == 0)
            continue;
        if (isPureAscii)
            isPureAscii = false;
        if (skip < 0)
        {
            isUtf8Valid = false;
            // if invalid utf8 is detected, there's no sense in going on.
            break;
        }
        i += skip;
    }
    if (isPureAscii)
        encoding = new ASCIIEncoding(); // pure 7-bit ascii.
    else if (isUtf8Valid)
        encoding = new UTF8Encoding(false);
    // else, retain given encoding. This should be an 8-bit encoding like Windows-1252.
    return encoding.GetString(docBytes);
}

/// <summary>
/// Tests if the bytes following the given offset are UTF-8 valid, and
/// returns the amount of bytes to skip ahead to do the next read if it is.
/// If the text is not UTF-8 valid it returns -1.
/// </summary>
/// <param name="binFile">Byte array to test</param>
/// <param name="offset">Offset in the byte array to test.</param>
/// <returns>The amount of bytes to skip ahead for the next read, or -1 if the byte sequence wasn't valid UTF-8</returns>
public static Int32 TestUtf8(Byte[] binFile, Int32 offset)
{
    // 7 bytes (so 6 added bytes) is the maximum the UTF-8 design could support,
    // but in reality it only goes up to 3, meaning the full amount is 4.
    const Int32 maxUtf8Length = 4;
    Byte current = binFile[offset];
    if ((current & 0x80) == 0)
        return 0; // valid 7-bit ascii. Added length is 0 bytes.
    Int32 len = binFile.Length;
    for (Int32 addedlength = 1; addedlength < maxUtf8Length; ++addedlength)
    {
        Int32 fullmask = 0x80;
        Int32 testmask = 0;
        // This code adds shifted bits to get the desired full mask.
        // If the full mask is [111]0 0000, then test mask will be [110]0 0000. Since this is
        // effectively always the previous step in the iteration I just store it each time.
        for (Int32 i = 0; i <= addedlength; ++i)
        {
            testmask = fullmask;
            fullmask += (0x80 >> (i+1));
        }
        // figure out bit masks from level
        if ((current & fullmask) == testmask)
        {
            if (offset + addedlength >= len)
                return -1;
            // Lookahead. Pattern of any following bytes is always 10xxxxxx
            for (Int32 i = 1; i <= addedlength; ++i)
            {
                if ((binFile[offset + i] & 0xC0) != 0x80)
                    return -1;
            }
            return addedlength;
        }
    }
    // Value is greater than the maximum allowed for utf8. Deemed invalid.
    return -1;
}
Nyerguds
la source
Il n'y a pas non plus de dernière elsedéclaration après if ((current & 0xE0) == 0xC0) { ... } else if ((current & 0xF0) == 0xE0) { ... } else if ((current & 0xF0) == 0xE0) { ... } else if ((current & 0xF8) == 0xF0) { ... }. Je suppose que le elsecas serait UTF8 invalide: isUtf8Valid = false;. Voudriez-vous?
hal le
@hal Ah, vrai ... depuis, j'ai mis à jour mon propre code avec un système plus général (et plus avancé) qui utilise une boucle allant jusqu'à 3 mais qui peut techniquement être modifiée pour boucler plus loin (les spécifications sont un peu floues à ce sujet ; il est possible d'étendre UTF-8 jusqu'à 6 octets ajoutés je pense, mais seulement 3 sont utilisés dans les implémentations actuelles), donc je n'ai pas mis à jour ce code.
Nyerguds
@hal l'a mis à jour avec ma nouvelle solution. Le principe reste le même, mais les masques de bits sont créés et vérifiés dans une boucle plutôt que tous écrits explicitement dans le code.
Nyerguds
1

J'ai trouvé une nouvelle bibliothèque sur GitHub: CharsetDetector / UTF-unknown

Détecteur de jeu de caractères construit en C # - .NET Core 2-3, .NET standard 1-2 et .NET 4+

c'est aussi un port du Mozilla Universal Charset Detector basé sur d'autres référentiels.

CharsetDetector / UTF-unknown ont une classe nommée CharsetDetector.

CharsetDetector contient des méthodes de détection de codage statique:

  • CharsetDetector.DetectFromFile()
  • CharsetDetector.DetectFromStream()
  • CharsetDetector.DetectFromBytes()

le résultat détecté est dans la classe DetectionResulta l'attribut Detectedqui est l'instance de la classe DetectionDetailavec les attributs ci-dessous:

  • EncodingName
  • Encoding
  • Confidence

ci-dessous est un exemple pour montrer l'utilisation:

// Program.cs
using System;
using System.Text;
using UtfUnknown;

namespace ConsoleExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string filename = @"E:\new-file.txt";
            DetectDemo(filename);
        }

        /// <summary>
        /// Command line example: detect the encoding of the given file.
        /// </summary>
        /// <param name="filename">a filename</param>
        public static void DetectDemo(string filename)
        {
            // Detect from File
            DetectionResult result = CharsetDetector.DetectFromFile(filename);
            // Get the best Detection
            DetectionDetail resultDetected = result.Detected;

            // detected result may be null.
            if (resultDetected != null)
            {
                // Get the alias of the found encoding
                string encodingName = resultDetected.EncodingName;
                // Get the System.Text.Encoding of the found encoding (can be null if not available)
                Encoding encoding = resultDetected.Encoding;
                // Get the confidence of the found encoding (between 0 and 1)
                float confidence = resultDetected.Confidence;

                if (encoding != null)
                {
                    Console.WriteLine($"Detection completed: {filename}");
                    Console.WriteLine($"EncodingWebName: {encoding.WebName}{Environment.NewLine}Confidence: {confidence}");
                }
                else
                {
                    Console.WriteLine($"Detection completed: {filename}");
                    Console.WriteLine($"(Encoding is null){Environment.NewLine}EncodingName: {encodingName}{Environment.NewLine}Confidence: {confidence}");
                }
            }
            else
            {
                Console.WriteLine($"Detection failed: {filename}");
            }
        }
    }
}

exemple de capture d'écran de résultat: entrez la description de l'image ici

gsw945
la source