Existe-t-il un meilleur moyen de convertir en ASCII à partir d’une entrée arbitraire?

StackOverflow https://stackoverflow.com/questions/309734

  •  08-07-2019
  •  | 
  •  

Question

Je dois être en mesure de prendre une entrée de texte arbitraire pouvant comporter un marqueur d'ordre de byte (BOM) pour marquer son codage, et de le générer au format ASCII. Nous avons d'anciens outils qui ne comprennent pas les nomenclatures et j'ai besoin de leur envoyer des données uniquement en ASCII.

Maintenant, je viens juste d’en finir avec l’écriture de ce code et je ne peux tout simplement pas croire l’inefficacité. Quatre copies des données, sans oublier les tampons intermédiaires internes à StreamReader. Y a-t-il une meilleure façon de faire cela?

// i_fileBytes is an incoming byte[]

string unicodeString = new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd();
byte[] unicodeBytes  = Encoding.Unicode.GetBytes(unicodeString.ToCharArray());
byte[] ansiBytes     = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes);
string ansiString    = Encoding.ASCII.GetString(ansiBytes);

J'ai besoin de StreamReader () car il possède un détecteur de nomenclature interne pour choisir l’encodage permettant de lire le reste du fichier. Ensuite, le reste consiste simplement à le convertir en chaîne ASCII finale.

Y a-t-il une meilleure façon de faire cela?

Était-ce utile?

La solution

Si vous avez déjà i_fileBytes en mémoire, vous pouvez simplement vérifier si elle commence par une nomenclature, puis convertir le tout ou juste le bit après la nomenclature à l'aide de Encoding.Unicode.GetString. . (Utilisez la surcharge qui vous permet de spécifier un index et une longueur.)

Donc en tant que code:

int start = (i_fileBytes[0] == 0xff && i_fileBytes[1] == 0xfe) ? 2 : 0;
string text = Encoding.Unicode.GetString(i_fileBytes, start, i_fileBytes.Length-start);

Notez que cela suppose cependant un encodage UTF-16 véritablement little-endian. Si vous devez d'abord détecter le codage, vous pouvez soit réimplémenter ce que fait StreamReader, soit peut-être simplement créer un StreamReader à partir du premier octet (disons) 10, et utiliser la propriété CurrentEncoding pour déterminer ce que vous devriez utiliser pour l'encodage.

EDIT: Maintenant, en ce qui concerne la conversion en ASCII - si vous n’avez vraiment besoin que d’une chaîne .NET, alors tout ce que vous voudriez faire est probablement de remplacer les caractères non-ASCII par des "&?"? ou quelque chose de similaire. (Sinon, il pourrait être préférable de lancer une exception ... à vous de choisir, bien sûr.)

EDIT: Notez que lors de la détection du codage, il serait judicieux d’appeler Read () une seule fois pour lire un caractère. N'appelez pas ReadToEnd () en choisissant 10 octets comme quantité arbitraire de données, cela pourrait se terminer au milieu du caractère. Je ne sais pas si cela jetterait une exception, mais cela n’a aucun avantage de toute façon ...

Autres conseils

System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

Cela devrait économiser quelques allers-retours.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top