Pregunta

Necesito poder tomar una entrada de texto arbitraria que puede tener un marcador de orden de bytes (BOM) para marcar su codificación y generarla como ASCII. Tenemos algunas herramientas antiguas que no entienden las listas de materiales y necesito enviarles datos solo ASCII.

Ahora, acabo de terminar de escribir este código y no puedo creer la ineficiencia aquí. Cuatro copias de los datos, sin mencionar los buffers intermedios internos en StreamReader. ¿Hay una mejor manera de hacer esto?

// 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);

Necesito el StreamReader () porque tiene un detector BOM interno para elegir la codificación para leer el resto del archivo. Luego, el resto es solo para convertirlo en la cadena ASCII final.

¿Hay una mejor manera de hacer esto?

¿Fue útil?

Solución

Si ya tiene i_fileBytes en la memoria, puede verificar si comienza con una lista de materiales o no, y luego convertir todo o solo un poco después de la lista de materiales usando Encoding.Unicode.GetString . (Use la sobrecarga que le permite especificar un índice y una longitud).

Entonces, como código:

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

Tenga en cuenta que eso supone una codificación UTF-16 genuinamente poco endian, sin embargo. Si realmente necesita detectar la codificación primero, puede volver a implementar lo que hace StreamReader, o tal vez simplemente construir un StreamReader a partir de los primeros (digamos) 10 bytes, y usar la propiedad CurrentEncoding para resolver lo que debe > uso para la codificación.

EDITAR: ahora, en cuanto a la conversión a ASCII, si realmente solo lo necesita como una cadena .NET, entonces presumiblemente todo lo que quiere hacer es reemplazar cualquier carácter que no sea ASCII con "? " o algo similar. (Alternativamente, podría ser mejor lanzar una excepción ... eso depende de usted, por supuesto).

EDITAR: tenga en cuenta que al detectar la codificación, sería una buena idea llamar a Read () una sola vez para leer un carácter. No llame a ReadToEnd () porque al elegir 10 bytes como una cantidad arbitraria de datos, podría terminar a mitad de carácter. No sé de antemano si eso arrojaría una excepción, pero de todos modos no tiene beneficios ...

Otros consejos

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

Eso debería ahorrar algunos viajes de ida y vuelta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top