C # Converte la stringa da UTF-8 a ISO-8859-1 (Latin1) H


103

Ho cercato su Google questo argomento e ho esaminato ogni risposta, ma ancora non riesco a capirlo.

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

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

La mia stringa di origine è

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

Ma sfortunatamente la mia stringa di risultati diventa

msg = "�ä�ö�õ�ü

Cosa sto facendo di sbagliato qui?


5
Tutte le stringhe in .NET memorizzano internamente le stringhe utilizzando caratteri Unicode. Non esiste la nozione di una stringa come "windows-1252", "iso-8859-1", "utf-8", ecc. Stai tentando di eliminare i caratteri nella tua stringa che non hanno una rappresentazione in Windows -1252 tabella codici?
Ian Boyd

1
@IanBoyd In realtà, una stringa è una sequenza conteggiata di unità di codice UTF-16. (Sfortunatamente, il termine Unicode è stato applicato erroneamente Encoding.Unicodenell'API Win32. Unicode è un set di caratteri, non una codifica. UTF-16 è una delle numerose codifiche per Unicode.)
Tom Blodget

1
Fai un'azione sbagliata: crei un array di byte nella codifica utf8, ma li leggi per decodifica iso. Se vuoi creare una stringa con simboli codificati, chiama semplicemente string msg = iso.GetString (iso.GetBytes (Message));
StuS

Si chiama Mojibake.
Rick James

Immagino che quello che sta dicendo Daniil sia che è Messagestato decodificato da UTF-8. Supponendo che quella parte funzioni correttamente, la conversione in Latin-1 è semplice come byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message). Quindi, come dice StuS, puoi riconvertire i byte Latin-1 in UTF-16 conEncoding.GetEncoding("ISO-8859-1").GetString(bytes)
Qwertie

Risposte:


176

Utilizzare Encoding.Convert per regolare l'array di byte prima di tentare di decodificarlo nella codifica di 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);

7
L'unica linea èEncoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString)))

1
Se crei tu stesso la stringa all'interno di C # /. Net, questo codice non è corretto al 100%, devi codificare da UTF-16 (che è la variabile "Unicode"). Perché questa è l'impostazione predefinita. Quindi UTF8 nel codice sopra deve essere cambiato in Unicode.
goamn

Consiglio di usare questo: Encoding iso = Encoding.GetEncoding ("ISO-8859-9"); Perché la codifica turca copre quasi tutto l'alfabeto esteso dal latino.
Fuat

26

Penso che il tuo problema sia che presumi che i byte che rappresentano la stringa utf8 risulteranno nella stessa stringa quando interpretati come qualcos'altro (iso-8859-1). E semplicemente non è così. Ti consiglio di leggere questo eccellente articolo di Joel Spolsky.


1
Ottimo articolo davvero e con un senso dell'umorismo! Oggi al lavoro stavo affrontando un problema di codifica e questo mi ha aiutato.
Pantelis

16

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

perché ricevo lo stesso messaggio utf-8? Al posto del messaggio ho passato la stringa messaggio = <name> sdjfhsjdf </name> .quindi lo stesso output viene inserito in msg variabile. come ottenere dati latini?
user1237131

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

2
Encoding.Convert genera un'eccezione di fallback durante la conversione se la stringa contiene caratteri non iso
Tertium

8

È necessario innanzitutto correggere l'origine della stringa.

Una stringa in .NET è in realtà solo un array di punti di codice Unicode a 16 bit, caratteri, quindi una stringa non è in una codifica particolare.

È quando prendi quella stringa e la converti in un insieme di byte che entra in gioco la codifica.

In ogni caso, il modo in cui l'hai fatto, codificando una stringa in un array di byte con un set di caratteri, e poi decodificandola con un altro, non funzionerà, come vedi.

Puoi dirci di più sulla provenienza di quella stringa originale e perché pensi che sia stata codificata in modo sbagliato?


Viene direttamente da App.config e stavo pensando che fosse UTF8 per impostazione predefinita. Grazie!
Daniil Harik

La codifica di quel file potrebbe influire sul modo in cui il file viene interpretato, quindi lo guarderei.
Lasse V. Karlsen

2
Correggimi se sbaglio, ma ho capito che, sebbene tecnicamente "non sia in una codifica particolare", una stringa .NET è un array di byte che corrisponde esattamente a un file UTF-16, byte per byte (escluso la distinta base). Utilizza anche i surrogati allo stesso modo (il che sembra un trucco di codifica). Ovviamente, in genere si desidera archiviare i file come UTF-8 ma elaborare i dati in memoria come 16 bit. (O 32 bit, per evitare la complessità delle coppie surrogate, anche se non sono sicuro che sia davvero fattibile.)
Jon Coombs,

6

Sembra un po 'strano il codice. Per ottenere una stringa dal flusso di byte Utf8 tutto ciò che devi fare è:

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

Se è necessario salvare il flusso di byte iso-8859-1 da qualche parte, utilizzare semplicemente: riga di codice aggiuntiva per il precedente:

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

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

1
Pienamente d'accordo. Quando hai già UTF-16, è abbastanza difficile trasformarlo in una codifica corretta, perché quando hai convertito un array di byte in una stringa con una codifica errata, c'è già una perdita di informazioni.
Sander A

0

Ho appena usato la soluzione di Nathan e funziona bene. Avevo bisogno di convertire ISO-8859-1 in 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 = "mail@xxxxxx.org";
    SmtpClient client = new SmtpClient("mail.xxxxx.org");
    MailMessage message = new MailMessage(Email, "mail@someone.com", "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);}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.