2017-09-01 1 views
3

J'ai du texte UTF-8 dans un fichier utf8.txt. Le fichier contient des caractères qui sont en dehors de la plage ASCII. J'ai essayé le code suivant:System.IO.File.ReadAllText ne lançant pas d'exception pour un codage non valide

var fname = "utf8.txt"; 
var enc = Encoding.GetEncoding("ISO-8859-1", EncoderFallback.ExceptionFallback, 
    DecoderFallback.ExceptionFallback); 
var s = System.IO.File.ReadAllText(fname, enc); 

Le comportement attendu est que le code devrait lancer une exception, car il n'est pas valide texte ISO-8859-1. Au lieu de cela, le comportement est qu'il décode correctement le texte UTF-8 dans les bons caractères (il semble correct dans le débogueur).

Est-ce un bug dans .Net?

EDIT:

Le fichier I testé avec l'origine était UTF-8 avec BOM. Si je supprime la nomenclature, le comportement change. Il toujours ne lève pas une exception, mais il produit une chaîne Unicode incorrecte (la chaîne ne pas semble correcte dans le débogueur).

EDIT:

Pour produire mon fichier de test, exécutez le code suivant:

var fname = "utf8.txt"; 
var utf8_bom_e_circumflex_bytes = new byte[] {0xEF, 0xBB, 0xBF, 0xC3, 0xAA}; 
System.IO.File.WriteAllBytes(fname, utf8_bom_e_circumflex_bytes); 

EDIT:

Je pense avoir une poignée ferme sur ce qui se passe (même si je ne suis pas d'accord avec une partie du comportement de .Net).

  • Si le fichier commence par UTF-8 BOM, et les données sont UTF-8, puis ReadAllText valide ignorera complètement le codage vous avez passé et (correctement) décoder le fichier en UTF-8. (Je n'ai pas testé ce qui se passe si la BOM est un mensonge et le fichier n'est pas vraiment UTF-8) Je ne suis pas d'accord avec ce comportement. Je pense que .Net devrait soit jeter une exception ou utiliser l'encodage que je lui ai donné.

  • Si le fichier n'a pas de nomenclature, .Net n'a aucun moyen trivial (et 100% fiable) de déterminer que le texte n'est pas réellement ISO-8859-1, car la plupart (tout?) Du texte UTF-8 est également ISO-8859-1 valide, bien que charabia. Donc, il suit simplement vos instructions et décode le fichier avec l'encodage que vous lui avez donné. (Je suis d'accord avec ce comportement)

+0

Pouvez-vous fournir un échantillon du texte dans le fichier que vous pensez être problématique? – DontThinkJustGo

+0

J'ai pensé à cela, mais quelle est la meilleure façon de le faire? Je voudrais vraiment publier un fichier binaire. – JoelFan

+0

peut-être juste un couple encodages de caractères que vous attendez à l'échec, et nous pouvons recréer le texte basé sur cela? Ou peut-être que je peux juste sortir et trouver un texte utf8 obscur et l'utiliser. Je suppose que ce n'est pas un caractère spécifique, juste un caractère ISO-8859-1 invalide qui vous préoccupe – DontThinkJustGo

Répondre

1

devrait lancer une exception, car il n'est pas valide texte ISO-8859-1

Dans ISO-8859-1 tous les octets possibles ont mappings aux caractères, aucune exception ne résultera jamais de la lecture d'un fichier non-ISO-8859-1 comme ISO-8859-1.

(Vrai, tous les octets dans la plage 0x80-0x9F deviendront des codes de contrôle invisibles que vous ne voulez jamais, mais ils sont toujours valides, tout simplement inutiles .C'est le cas pour un grand nombre d'encodages ISO-8859, qui met les codes de contrôle C1 dans la plage 0x80-0x9F, mais pas tous.Vous pouvez certainement obtenir une exception avec d'autres encodages qui laissent des octets non mappés, par exemple Windows-1252.)

Si le fichier commence par UTF-8 BOM et les données sont valides UTF-8, puis ReadAllText sera complètement ignorer l'encodage que vous avez passé et (correctement) décoder le fichier en UTF-8.

Yep. Cela est indiqué dans le document:

This method attempts to automatically detect the encoding of a file based on the presence of byte order marks. 

Je suis d'accord avec vous que ce comportement est assez stupide. Je préférerais ReadAllBytes et vérifier par Encoding.GetString manuellement.