2009-06-16 7 views
0

J'ai remarqué un comportement étrange de File.Copy() dans .NET 3.5SP1. Je ne sais pas si c'est un bug ou une fonctionnalité. Mais je sais que ça me rend fou. Nous utilisons File.Copy() dans une étape de construction personnalisée, et il vissera l'encodage de caractères. Lorsque je copie un fichier texte d'encodage ASCII sur un fichier texte codé en UTF-8, le fichier de destination est toujours codé en UTF-8, mais contient le contenu du nouveau fichier plus les 3 caractères préfixés pour UTF-8. C'est bien pour les caractères ASCII, mais incorrect pour les caractères restants (128-255) de la page de code ANSI.File.Copy et le codage de caractères

Voici le code à reproduire. Je copie d'abord un fichier UTF-8 vers la destination, puis je copie un fichier ANSI vers la même destination. Notez la sortie de la deuxième sortie de la console: Content of copy.txt : this is ASCII encoded:/Encoding: utf-8

File.WriteAllText("ANSI.txt", "this is ANSI encoded: é", Encoding.GetEncoding(0)); 
File.WriteAllText("UTF8.txt", "this is UTF8 encoded: é", Encoding.UTF8); 

File.Copy("UTF8.txt", "copy.txt", true); 

using (StreamReader reader = new StreamReader("copy.txt", true)) 
{ 
    Console.WriteLine("Content of copy.txt : " + reader.ReadToEnd() + "/Encoding: " + 
       reader.CurrentEncoding.BodyName); 
} 

File.Copy("ANSI.txt", "copy.txt", true); 

using (StreamReader reader = new StreamReader("copy.txt", true)) 
{ 
    Console.WriteLine("Content of copy.txt : " + reader.ReadToEnd() + "/Encoding: " + 
       reader.CurrentEncoding.BodyName); 
} 

Toutes les idées pourquoi cela se produit? Y a-t-il une erreur dans mon code? Toutes les idées comment résoudre ce problème (mon idée actuelle est de supprimer le fichier avant si elle existe)

EDIT: correcte confusion ANSI/ASCII

Répondre

1

Où écrivez-vous ASCII.txt? Vous écrivez ANSI.txt dans la première ligne, mais ce n'est certainement pas ASCII car ASCII ne contient aucun caractère accentué. Le fichier ANSI ne contiendra aucun préambule indiquant que c'est ANSI plutôt que ASCII ou UTF-8.

Vous semblez avoir changé d'avis entre ASCII et ANSI à mi-chemin de l'écriture de l'exemple, essentiellement. Je m'attendrais à ce que n'importe quel fichier ASCII soit "détecté" comme UTF-8, mais la détection de codage repose sur le fichier ayant une marque d'ordre d'octet pour qu'il soit autre chose que UTF-8. Ce n'est pas comme s'il lisait tout le fichier et devinait ensuite l'encodage.

De la documentation pour StreamReader:

Ce constructeur initialise le codant pour UTF8Encoding, la propriété de BaseStream utilisant le paramètre courant , et la mémoire tampon interne pour la taille par défaut.

Le paramètre detectEncodingFromByteOrderMarks détecte le codage par regardant les trois premiers octets de le flux. Il reconnaît automatiquement UTF-8, little-endian Unicode et big-endian texte Unicode si le fichier commence par les marques d'ordre d'octet appropriées. Voir la méthode Encoding.GetPreamble pour plus d'informations .

Maintenant File.Copy est tout simplement copier les octets bruts d'un endroit à - il ne devrait pas changer quoi que ce soit en termes de codages de caractères, car il ne cherche pas à interpréter le fichier en tant que fichier texte dans le premier endroit.

Ce n'est pas très clair pour moi où vous voyez un problème (dû en partie à la partie ANSI/ASCII). Je vous suggère de séparer les questions de "fait File.Copy changer les choses?" et "quel encodage de caractères est détecté par StreamReader?" à la fois dans votre esprit et votre question.Les réponses doivent être:

  • File.Copy ne devrait pas modifier le contenu du fichier du tout
  • StreamReader ne peut détecter UTF-8 et UTF-16; Si vous avez besoin de lire un fichier encodé avec un autre encodage, vous devez l'indiquer explicitement dans le constructeur. (Personnellement, je recommande l'utilisation Encoding.Default au lieu de Encoding.GetEncoding(0) par la manière. Je pense qu'il est plus clair.)
+0

Le problème n'est pas StreamReader. Je l'ai seulement utilisé pour créer un court morceau de code qui peut reproduire le problème. (et j'ai foiré depuis que j'ai confondu ASCII et ANSI en jouant avec ça). Je l'ai remarqué d'abord dans un éditeur hexadécimal, et à ma connaissance le fichier résultant est incorrect, car il a la marque d'ordre octet UTF-8 (3 octets au début) et un mauvais code caractère pour le caractère accentué – chris166

+0

Quelque chose est bizarre. Je ne suis plus capable de le reproduire. Donc, quelque chose était obsolète (mon éditeur hexadécimal, le code dans VS ou autre). Quoi qu'il en soit, merci d'avoir examiné le problème et de passer autant de temps dessus! – chris166

+0

Mon plaisir - même si cela n'a pas pris beaucoup plus de temps qu'il n'en fallait pour taper la réponse. D'autres questions ont parfois absorbé * beaucoup * plus d'efforts :) –

0

Je doute que cela n'a rien à voir avec File.Copy. Je pense que ce que vous voyez est que StreamReader utilise UTF-8 par défaut pour décoder et comme UTF-8 est rétrocompatible, StreamReader n'a aucune raison d'arrêter d'utiliser UTF-8 pour lire le fichier codé ANSI.

Si vous ouvrez ASCII.txt et copy.txt dans un éditeur hexadécimal, sont-ils identiques?

+0

Non, la détection d'encodage de StreamReader fonctionne correctement. Le fichier copy.txt a la marque d'ordre des octets UTF-8 au début et le mauvais caractère pour le caractère truqué. – chris166

Questions connexes