2009-12-17 5 views
80

Ho cercato su questo argomento e ho esaminato ogni risposta, ma ancora non la capisco.C# Convertire la stringa da UTF-8 a ISO-8859-1 (Latin1) H

Fondamentalmente ho bisogno di convertire stringa UTF-8 a ISO-8859-1 e lo faccio usando seguente codice:

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

mia stringa di origine è

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

Ma purtroppo la mia stringa risultato diventa

msg = "�ä�ö�õ�ü 

Cosa sto facendo male qui?

+3

Tutte le stringhe in .NET memorizzano internamente le stringhe utilizzando caratteri unicode. Non c'è alcuna idea che una stringa sia "windows-1252", "iso-8859-1", "utf-8", ecc. Stai cercando di gettare via qualsiasi carattere nella tua stringa che non ha una rappresentazione in Windows -1252 tabella codici? –

+0

@IanBoyd In realtà, una [stringa] (https://msdn.microsoft.com/en-us/library/system.string (v = vs.110) .aspx) è una sequenza contata di unità di codice UTF-16. (Sfortunatamente, il termine Unicode è stato applicato in modo errato in 'Encoding.Unicode' e nell'API Win32. Unicode è un set di caratteri, non una codifica. UTF-16 è una delle diverse codifiche per Unicode.) –

+0

L'azione non è corretta: crea array di byte nella codifica utf8, ma li legge con decodifica iso. Se vuoi creare string con simboli codificati chiama semplicemente ** string msg = iso.GetString (iso.GetBytes (Message)); ** – StuS

risposta

121

Usa Encoding.Convert per regolare l'array di byte prima di tentare di decodificare nella tua codifica destinazione.

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

L'unico elemento è 'Encoding.GetEncoding (" ISO-8859-1 "). GetString (Encoding.Convert (Encoding.UTF8, Encoding.GetEncoding (" ISO-8859-1 "), Encoding.UTF8.GetBytes (myString)))' –

+0

Se si sta creando la stringa da soli in C# /. Net, allora questo codice non è corretto al 100%, è necessario codificare da UTF-16 (che è la variabile "Unicode"). Perché questo è l'impostazione predefinita. Quindi UTF8 nel codice sopra deve essere cambiato in Unicode. – goamn

7

È necessario correggere l'origine della stringa in primo luogo.

Una stringa in .NET è in realtà solo una matrice di punti di codice unicode a 16 bit, caratteri, quindi una stringa non è in alcuna codifica particolare.

È quando si prende quella stringa e si converte in una serie di byte che la codifica entra in gioco.

In ogni caso, come hai fatto tu, hai codificato una stringa in un array di byte con un set di caratteri e poi decodificandolo con un altro, non funzionerà, come vedi.

Puoi dirci di più su da dove proviene quella stringa originale e perché pensi che sia stata codificata in modo errato?

+0

Arriva direttamente da App.config e stavo pensando che sia impostato su UTF8 per impostazione predefinita. Grazie! –

+0

La codifica di quel file potrebbe influire sul modo in cui il file viene interpretato, quindi guarderei a quello. –

+2

Correggetemi se ho torto, ma la mia comprensione è che, mentre tecnicamente "non è in alcuna particolare codifica", una stringa .NET è una matrice di byte che corrisponde precisamente a un file UTF-16, byte per byte (esclusa la distinta base). Utilizza anche surrogati allo stesso modo (che sembra un trucco di codifica). Naturalmente, in genere si desidera archiviare i file come UTF-8 ma elaborare i dati in memoria come 16 bit. (Oppure 32-bit, per evitare la complessità delle coppie surrogate, anche se non sono sicuro che sia davvero fattibile.) –

19

Penso che il vostro problema è che si presume che i byte che rappresentano la stringa utf8 risulteranno nella stessa stringa quando interpretati come qualcos'altro (iso-8859-1). E questo semplicemente non è il caso. Vi consiglio di leggere this excellent article di Joel Spolsky.

+0

Grazie ... lo farò! –

+0

Ottimo articolo davvero e con un senso dell'umorismo! Stavo affrontando un problema di codifica oggi al lavoro e questo mi ha aiutato. – Pantelis

14

Prova questo:

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

perché sto ricevendo lo stesso messaggio utf-8? Al posto del messaggio ho passato il messaggio stringa = sdjfhsjdf .questo stesso risultato è stato visualizzato in msg varieable.how per ottenere dati latini? – user1237131

+0

Questo funziona per me. Ricordati di includere lo spazio dei nomi System.Text. – Spawnrider

+2

Encoding.Convert genera un'eccezione di fallback durante la conversione se la stringa ha caratteri non-iso – Tertium

4

Sembra un po 'strano codice. Per ottenere stringhe di byte da UTF8 flusso di tutto quello che dovete fare è:

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

Se è necessario salvare flusso di byte iso-8859-1 da qualche parte poi basta usare: riga aggiuntiva di codice per precedente:

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

Questa è chiaramente la risposta più semplice. Il problema nel codice è infatti che l'autore sembra presumere che una stringa in C# possa già essere archiviata "usando" una certa codifica, che semplicemente non è vera; sono sempre UTF16 internamente. – Nyerguds

+1

Pienamente d'accordo. Quando hai già UTF-16, è abbastanza difficile farlo nella codifica corretta, perché quando hai convertito l'array di byte in una stringa con codifica errata c'è già una perdita di informazioni. –

0

Ho appena usato la soluzione di Nathan e funziona perfettamente. Avevo bisogno di convertire 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

Ecco un esempio per 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);}