Usando .NET cómo convertir archivos de texto codificados ISO 8859-1 que contienen caracteres acentuados Latin-1 a UTF-8

Me están enviando archivos de texto guardados en formato ISO 88591-1 que contienen caracteres acentuados del rango Latin-1 (así como ASCII az normal, etc.). ¿Cómo convierto estos archivos a UTF-8 usando C # para que los caracteres acentuados de un solo byte en ISO 8859-1 se conviertan en caracteres UTF-8 válidos?

Intenté usar un StreamReader con ASCIIEncoding y luego convertir la cadena ASCII a UTF-8 instanciando la encoding ascii y codificando utf8 y luego usando Encoding.Convert(ascii, utf8, ascii.GetBytes( asciiString) ) , pero los caracteres acentuados se presentan como signos de interrogación.

¿Qué paso me estoy perdiendo?

Necesita obtener el objeto de Encoding adecuado. ASCII tiene el mismo nombre: ASCII, lo que significa que solo admite caracteres ASCII de 7 bits. Si lo que quiere hacer es convertir archivos, entonces esto es más fácil que tratar directamente con las matrices de bytes.

 using (System.IO.StreamReader reader = new System.IO.StreamReader(fileName, Encoding.GetEncoding("iso-8859-1"))) { using (System.IO.StreamWriter writer = new System.IO.StreamWriter( outFileName, Encoding.UTF8)) { writer.Write(reader.ReadToEnd()); } } 

Sin embargo, si quiere tener las matrices de bytes usted mismo, es bastante fácil hacerlo con Encoding.Convert .

 byte[] converted = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8, data); 

Sin embargo, es importante tener en cuenta que si desea seguir este camino, no debe usar un lector de cadenas basado en encoding como StreamReader para su archivo IO. FileStream sería más adecuado, ya que leerá los bytes reales de los archivos.

Con el interés de explorar completamente el problema, algo como esto funcionaría:

 using (System.IO.FileStream input = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { byte[] buffer = new byte[input.Length]; int readLength = 0; while (readLength < buffer.Length) readLength += input.Read(buffer, readLength, buffer.Length - readLength); byte[] converted = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8, buffer); using (System.IO.FileStream output = new System.IO.FileStream(outFileName, System.IO.FileMode.Create, System.IO.FileAccess.Write)) { output.Write(converted, 0, converted.Length); } } 

En este ejemplo, la variable del buffer se llena con los datos reales en el archivo como un byte[] , por lo que no se realiza ninguna conversión. Encoding.Convert especifica una fuente y una encoding de destino, luego almacena los bytes convertidos en la variable llamada ... converted . Esto se escribe en el archivo de salida directamente.

Como dije, la primera opción que use StreamReader y StreamWriter será mucho más simple si esto es todo lo que estás haciendo, pero el último ejemplo debería darte más pistas sobre lo que está sucediendo realmente.

Si los archivos son relativamente pequeños (digamos, ~ 10 megabytes), solo necesitará dos líneas de código:

  string txt = System.IO.File.ReadAllText(inpPath, Encoding.GetEncoding("iso-8859-1")); System.IO.File.WriteAllText(outPath, txt);