2009-12-17 62 views
80

He buscado en Google este tema y he examinado todas las respuestas, pero sigo sin entenderlo.C# Convertir cadena de UTF-8 a ISO-8859-1 (Latin1) H

Básicamente necesito para convertir cadena UTF-8 a ISO-8859-1 y lo hago usando siguiente código:

Encoding iso = Encoding.GetEncoding("ISO-8859-1"); 
Encoding utf8 = Encoding.UTF8; 
string msg = iso.GetString(utf8.GetBytes(Message)); 

Mi cadena de origen es

Message = "ÄäÖöÕõÜü" 

Pero por desgracia mi cadena de resultado se convierte en

msg = "�ä�ö�õ�ü 

¿Qué estoy haciendo mal aquí?

+3

Todas las cadenas en .NET almacenan internamente las cadenas usando caracteres Unicode. No hay idea de que una cadena sea "windows-1252", "iso-8859-1", "utf-8", etc. ¿Está tratando de descartar cualquier carácter de su cadena que no tenga una representación en Windows? -1252 página de códigos? –

+0

@IanBoyd En realidad, un [String] (https://msdn.microsoft.com/en-us/library/system.string (v = vs.110) .aspx) es una secuencia de contado de UTF-16 unidades de código. (. Por desgracia, el término Unicode ha sido mal aplicada en 'Encoding.Unicode' y en la API Win32 Unicode es un conjunto de caracteres, no una codificación UTF-16 es una de las varias codificaciones para Unicode..) –

+0

Haces acción incorrecta: se make byte array en la codificación utf8, pero léelos por iso decode. Si quieres hacer cadena con símbolos codificados es simple llamada ** cadena msg = iso.GetString (iso.GetBytes (mensaje)); ** – StuS

Respuesta

121

Uso Encoding.Convert para ajustar la matriz de bytes antes de intentar decodificar en la codificación de destino.

Encoding iso = Encoding.GetEncoding("ISO-8859-1"); 
Encoding utf8 = Encoding.UTF8; 
byte[] utfBytes = utf8.GetBytes(Message); 
byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes); 
string msg = iso.GetString(isoBytes); 
+4

La un trazador de líneas es 'Encoding.GetEncoding ("ISO-8859-1"). GetString (Encoding.Convert (Encoding.UTF8, Encoding.GetEncoding (" ISO-8859-1"), Encoding.UTF8.GetBytes (miCadena))) ' –

+0

Si va a crear la cadena de sí mismo dentro de C# /. Net, a continuación, este código no es 100% correcto, es necesario codificar de UTF-16 (que es la variable "Unicode"). Porque este es el predeterminado. Por lo tanto, UTF8 en el código anterior debe cambiarse a Unicode. – goamn

7

En primer lugar, necesita corregir el origen de la cadena.

Una cadena en .NET es en realidad una matriz de puntos de código Unicode de 16 bits, caracteres, por lo que una cadena no está en una codificación particular.

Es cuando toma esa cadena y la convierte en un conjunto de bytes que la codificación entra en juego.

En cualquier caso, la forma en que lo hizo, codificó una cadena en una matriz de bytes con un conjunto de caracteres y luego la decodificó con otra, no funcionará, como puede ver.

¿Puede decirnos más acerca de dónde proviene esa secuencia original y por qué cree que se ha codificado incorrectamente?

+0

Está llegando directamente desde App.config y yo estaba pensando que es UTF8 por defecto. ¡Gracias! –

+0

La codificación de ese archivo puede afectar la forma en que se interpreta el archivo, así que lo vería. –

+2

Corrígeme si estoy equivocado, pero mi entendimiento es que, aunque técnicamente "no está en ninguna codificación particular", una cadena .NET es una matriz de bytes que corresponde precisamente a un archivo UTF-16, byte para byte (excluyendo la lista de materiales). Incluso utiliza sustitutos de la misma manera (lo que parece un truco de codificación). Por supuesto, generalmente desea almacenar archivos como UTF-8 pero procesar los datos en la memoria como de 16 bits. (O 32 bits, para evitar la complejidad de los pares de sustitución, aunque no estoy seguro de si eso es realmente factible.) –

19

Creo que su problema es que supone que los bytes que representan la cadena utf8 darán como resultado la misma cadena cuando se interpreten como algo diferente (iso-8859-1). Y eso simplemente no es el caso. Le recomiendo que lea this excellent article por Joel spolsky.

+0

Gracias ... lo haré! –

+0

¡Excelente artículo de verdad y con sentido del humor! Estaba enfrentando un problema de codificación hoy en el trabajo y esto me ayudó. – Pantelis

14

Prueba esto:

Encoding iso = Encoding.GetEncoding("ISO-8859-1"); 
Encoding utf8 = Encoding.UTF8; 
byte[] utfBytes = utf8.GetBytes(Message); 
byte[] isoBytes = Encoding.Convert(utf8,iso,utfBytes); 
string msg = iso.GetString(isoBytes); 
+0

porqué estoy consiguiendo mismo mensaje UTF-8? En lugar del mensaje pasé mensaje de cadena = sdjfhsjdf .then misma salida ponerse en varieable.how msg para obtener datos latino? – user1237131

+0

Esto funciona para mí. Recuerde incluir el espacio de nombres System.Text. – Spawnrider

+2

Encoding.Convert lanza excepción de retorno mientras que la conversión si la cadena tiene caracteres no iso – Tertium

4

Parece un código extraño. Para obtener la cadena de bytes Utf8 corriente de todo lo que hay que hacer es:

string str = Encoding.UTF8.GetString(utf8ByteArray); 

Si necesitas ahorrar flujo de bytes iso-8859-1 a algún lugar a continuación, sólo tiene que utilizar: línea adicional de código para anterior:

byte[] iso88591data = Encoding.GetEncoding("ISO-8859-1").GetBytes(str); 
+0

Esta es claramente la respuesta más directa. El problema en el código es que el autor parece suponer que una Cadena en C# ya puede almacenarse "usando" cierta codificación, lo que simplemente no es cierto; siempre son UTF16 internamente. – Nyerguds

+1

Totalmente de acuerdo. Cuando ya tienes UTF-16, es bastante difícil convertirlo en una codificación correcta, porque cuando conviertes la matriz de bytes en una cadena con codificación incorrecta, ya hay pérdida de información. –

0

Acabo de utilizar la solución de Nathan y funciona bien. Necesitaba convertir ISO-8859-1 a Unicode:

string isocontent = Encoding.GetEncoding("ISO-8859-1").GetString(fileContent, 0, fileContent.Length); 
byte[] isobytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(isocontent); 
byte[] ubytes = Encoding.Convert(Encoding.GetEncoding("ISO-8859-1"), Encoding.Unicode, isobytes); 
return Encoding.Unicode.GetString(ubytes, 0, ubytes.Length); 
0
Encoding targetEncoding = Encoding.GetEncoding(1252); 
// Encode a string into an array of bytes. 
Byte[] encodedBytes = targetEncoding.GetBytes(utfString); 
// Show the encoded byte values. 
Console.WriteLine("Encoded bytes: " + BitConverter.ToString(encodedBytes)); 
// Decode the byte array back to a string. 
String decodedString = Encoding.Default.GetString(encodedBytes); 
-5

Este es un ejemplo de la norma ISO-8859-9;

protected void btnKaydet_Click(object sender, EventArgs e) 
{ 
    Response.Clear(); 
    Response.Buffer = true; 
    Response.ContentType = "application/vnd.openxmlformatsofficedocument.wordprocessingml.documet"; 
    Response.AddHeader("Content-Disposition", "attachment; filename=XXXX.doc"); 
    Response.ContentEncoding = Encoding.GetEncoding("ISO-8859-9"); 
    Response.Charset = "ISO-8859-9"; 
    EnableViewState = false; 


    StringWriter writer = new StringWriter(); 
    HtmlTextWriter html = new HtmlTextWriter(writer); 
    form1.RenderControl(html); 


    byte[] bytesInStream = Encoding.GetEncoding("iso-8859-9").GetBytes(writer.ToString()); 
    MemoryStream memoryStream = new MemoryStream(bytesInStream); 


    string msgBody = ""; 
    string Email = "[email protected]"; 
    SmtpClient client = new SmtpClient("mail.xxxxx.org"); 
    MailMessage message = new MailMessage(Email, "[email protected]", "ONLINE APP FORM WITH WORD DOC", msgBody); 
    Attachment att = new Attachment(memoryStream, "XXXX.doc", "application/vnd.openxmlformatsofficedocument.wordprocessingml.documet"); 
    message.Attachments.Add(att); 
    message.BodyEncoding = System.Text.Encoding.UTF8; 
    message.IsBodyHtml = true; 
    client.Send(message);}