C # Konvertieren Sie einen String von UTF-8 nach ISO-8859-1 (Latin1) H.

103

Ich habe zu diesem Thema gegoogelt und mir jede Antwort angesehen, aber ich verstehe sie immer noch nicht.

Grundsätzlich muss ich eine UTF-8-Zeichenfolge in ISO-8859-1 konvertieren und dies mit folgendem Code tun:

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

Meine Quellzeichenfolge ist

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

Aber leider wird meine Ergebniszeichenfolge

msg = "�ä�ö�õ�ü

Was mache ich hier falsch?

Daniil Harik
quelle
5
Alle Zeichenfolgen in .NET speichern die Zeichenfolgen intern mit Unicode-Zeichen. Es gibt keine Vorstellung davon, dass eine Zeichenfolge "windows-1252", "iso-8859-1", "utf-8" usw. ist. Versuchen Sie, Zeichen in Ihrer Zeichenfolge wegzuwerfen, die in Windows keine Darstellung haben -1252 Codepage?
Ian Boyd
1
@IanBoyd Tatsächlich ist ein String eine gezählte Folge von UTF-16- Codeeinheiten . (Leider wurde der Begriff Unicode in Encoding.Unicodeund in der Win32-API falsch angewendet . Unicode ist ein Zeichensatz, keine Codierung. UTF-16 ist eine von mehreren Codierungen für Unicode.)
Tom Blodget
1
Sie führen eine falsche Aktion aus: Sie erstellen ein Byte-Array in utf8-Codierung, lesen es jedoch durch ISO-Decodierung. Wenn Sie eine Zeichenfolge mit codierten Symbolen erstellen
StuS
Das heißt Mojibake.
Rick James
Ich denke, was Daniil sagt, ist, dass Messagees von UTF-8 dekodiert wurde. Vorausgesetzt, dieser Teil hat korrekt funktioniert, ist die Konvertierung in Latin-1 so einfach wie byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message). Dann können Sie, wie StuS sagt, die Latin-1-Bytes mitEncoding.GetEncoding("ISO-8859-1").GetString(bytes)
Qwertie

Antworten:

176

Verwenden Sie Encoding.Convert , um das Byte-Array anzupassen, bevor Sie versuchen, es in Ihre Zielcodierung zu dekodieren.

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);
Nathan Baulch
quelle
7
Der eine Liner istEncoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString)))
1
Wenn Sie die Zeichenfolge selbst in C # /. Net erstellen, ist dieser Code nicht 100% korrekt. Sie müssen von UTF-16 (der Variablen "Unicode") codieren. Weil dies die Standardeinstellung ist. Daher muss UTF8 im obigen Code in Unicode geändert werden.
Goamn
Ich empfehle Folgendes: Encoding iso = Encoding.GetEncoding ("ISO-8859-9"); Weil die türkische Kodierung fast alle aus dem Lateinischen stammenden Alphabete abdeckt.
Fuat
26

Ich denke, Ihr Problem ist, dass Sie davon ausgehen, dass die Bytes, die die utf8-Zeichenfolge darstellen, dieselbe Interpretation ergeben, wenn sie als etwas anderes interpretiert werden (iso-8859-1). Und das ist einfach nicht der Fall. Ich empfehle Ihnen, diesen ausgezeichneten Artikel von Joel Spolsky zu lesen.

Klaus Byskov Pedersen
quelle
1
Ausgezeichneter Artikel in der Tat und mit Sinn für Humor! Ich hatte heute bei der Arbeit ein Codierungsproblem und das hat mir geholfen.
Pantelis
16

Versuche dies:

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);
Manu
quelle
Warum erhalte ich dieselbe utf-8-Nachricht? Anstelle der Nachricht habe ich die Zeichenfolge message = <name> sdjfhsjdf </ name> übergeben.
user1237131
Das funktioniert bei mir. Denken Sie daran, den System.Text-Namespace einzuschließen.
Spawnrider
2
Encoding.Convert löst beim Konvertieren eine Fallback-Ausnahme aus, wenn der String Nicht-
Tertium
8

Sie müssen zuerst die Quelle der Zeichenfolge korrigieren.

Eine Zeichenfolge in .NET ist eigentlich nur ein Array von 16-Bit-Unicode-Codepunkten, Zeichen, sodass eine Zeichenfolge keine bestimmte Codierung aufweist.

Wenn Sie diese Zeichenfolge nehmen und in eine Reihe von Bytes konvertieren, kommt die Codierung ins Spiel.

Wie Sie sehen, funktioniert die Art und Weise, wie Sie eine Zeichenfolge in ein Byte-Array mit einem Zeichensatz codiert und dann mit einem anderen dekodiert haben, nicht.

Können Sie uns mehr darüber erzählen, woher diese ursprüngliche Zeichenfolge stammt und warum sie Ihrer Meinung nach falsch codiert wurde?

Lasse V. Karlsen
quelle
Es kommt direkt von App.config und ich dachte, es ist standardmäßig UTF8. Danke!
Daniil Harik
Die Codierung dieser Datei könnte sich auf die Interpretation der Datei auswirken, also würde ich mir das ansehen.
Lasse V. Karlsen
2
Korrigieren Sie mich, wenn ich falsch liege, aber ich verstehe, dass eine .NET-Zeichenfolge technisch gesehen "keine bestimmte Codierung aufweist", aber ein Byte-Array ist, das genau einer UTF-16-Datei entspricht, Byte für Byte (ausgenommen) die Stückliste). Es werden sogar Ersatzzeichen auf die gleiche Weise verwendet (was wie ein Codierungstrick erscheint). Natürlich möchten Sie Dateien im Allgemeinen als UTF-8 speichern, aber die Daten im Speicher als 16-Bit verarbeiten. (Oder 32-Bit, um die Komplexität von Ersatzpaaren zu vermeiden, obwohl ich nicht sicher bin, ob das wirklich machbar ist.)
Jon Coombs
6

Scheint etwas seltsamer Code. Um eine Zeichenfolge aus dem Utf8-Byte-Stream abzurufen, müssen Sie lediglich Folgendes tun:

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

Wenn Sie den ISO-8859-1-Byte-Stream irgendwo speichern müssen, verwenden Sie einfach: zusätzliche Codezeile für vorherige:

byte[] iso88591data = Encoding.GetEncoding("ISO-8859-1").GetBytes(str);
Schleifer A.
quelle
1
Dies ist eindeutig die einfachste Antwort. Das Problem im Code ist in der Tat, dass der Autor anzunehmen scheint, dass ein String in C # bereits "unter Verwendung" einer bestimmten Codierung gespeichert werden kann, was einfach nicht wahr ist. Sie sind immer intern UTF16.
Nyerguds
1
Stimme voll zu. Wenn Sie bereits über UTF-16 verfügen, ist es ziemlich schwierig, daraus eine korrekte Codierung zu machen, da bei der Konvertierung eines Byte-Arrays in einen String mit falscher Codierung bereits Informationsverlust auftritt.
Sander A
0

Ich habe gerade die Lösung von Nathan verwendet und sie funktioniert einwandfrei. Ich musste ISO-8859-1 in Unicode konvertieren:

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);
Nicolai Nita
quelle
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);
Tomáš Opis
quelle
-5

Hier ist ein Beispiel für 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);}
Engin Kamarot
quelle