C # Konversi string dari UTF-8 ke ISO-8859-1 (Latin1) H

103

Saya telah mencari di Google tentang topik ini dan saya telah melihat setiap jawaban, tetapi saya masih belum mengerti.

Pada dasarnya saya perlu mengubah string UTF-8 menjadi ISO-8859-1 dan saya melakukannya dengan menggunakan kode berikut:

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

String sumber saya adalah

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

Tapi sayangnya string hasil saya menjadi

msg = "�ä�ö�õ�ü

Apa yang saya lakukan salah di sini?

Daniil Harik
sumber
5
Semua string di .NET secara internal menyimpan string menggunakan karakter unicode. Tidak ada gagasan bahwa String adalah "windows-1252", "iso-8859-1", "utf-8", dll. Apakah Anda mencoba membuang karakter apa pun dalam string yang tidak memiliki representasi di Windows -1252 halaman kode?
Ian Boyd
1
@IanBoyd Sebenarnya, String adalah urutan unit kode UTF-16 yang dihitung. (Sayangnya, istilah Unicode telah salah diterapkan di Encoding.Unicodedan di Win32 API. Unicode adalah himpunan karakter, bukan penyandiaksaraan. UTF-16 adalah salah satu dari beberapa penyandiaksaraan untuk Unicode.)
Tom Blodget
1
Anda membuat tindakan yang salah: Anda membuat array byte dalam pengkodean utf8, tetapi membacanya dengan dekode iso. Jika Anda ingin membuat string dengan simbol yang disandikan, cukup panggil string msg = iso.GetString (iso.GetBytes (Message));
StuS
Itu disebut Mojibake.
Rick James
Saya kira apa yang dikatakan Daniil adalah yang Messagediterjemahkan dari UTF-8. Dengan asumsi bagian itu bekerja dengan benar, mengonversi ke Latin-1 semudah byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message). Kemudian, seperti yang dikatakan StuS, Anda dapat mengonversi Latin-1 byte kembali ke UTF-16 denganEncoding.GetEncoding("ISO-8859-1").GetString(bytes)
Qwertie

Jawaban:

176

Gunakan Encoding.Convert untuk menyesuaikan array byte sebelum mencoba mendekodekannya menjadi pengkodean tujuan Anda.

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
sumber
7
Satu baris adalahEncoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString)))
1
Jika Anda membuat string sendiri di dalam C # /. Net, maka kode ini tidak 100% benar, Anda perlu menyandikannya dari UTF-16 (yang merupakan variabel "Unicode"). Karena ini defaultnya. Jadi UTF8 pada kode di atas harus diubah menjadi Unicode.
goamn
Saya merekomendasikan untuk menggunakan ini: Encoding iso = Encoding.GetEncoding ("ISO-8859-9"); Karena pengkodean bahasa Turki mencakup hampir semua alfabet diperpanjang dari Latin.
Fuat
26

Saya pikir masalah Anda adalah Anda berasumsi bahwa byte yang mewakili string utf8 akan menghasilkan string yang sama ketika ditafsirkan sebagai sesuatu yang lain (iso-8859-1). Dan bukan itu masalahnya. Saya menyarankan Anda membaca artikel yang sangat bagus ini oleh Joel spolsky.

Klaus Byskov Pedersen
sumber
1
Artikel yang sangat bagus dan dengan selera humor! Saya menghadapi masalah encoding hari ini di tempat kerja dan ini membantu saya.
Pantelis
16

Coba ini:

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
sumber
mengapa saya mendapatkan pesan utf-8 yang sama? di tempat pesan saya melewati pesan string = <nama> sdjfhsjdf </name>. lalu output yang sama masuk ke msg varieable. bagaimana cara mendapatkan data latin?
pengguna1237131
Ini berhasil untuk saya. Ingatlah untuk menyertakan namespace System.Text.
Spawnrider
2
Encoding.Convert melempar pengecualian fallback saat mengonversi jika string memiliki karakter non-iso
Tertium
8

Anda harus memperbaiki sumber string di tempat pertama.

Sebuah string dalam .NET sebenarnya hanyalah sebuah array dari kode-poin unicode 16-bit, karakter, jadi string tidak ada dalam pengkodean tertentu.

Saat Anda mengambil string itu dan mengubahnya menjadi satu set byte, encoding mulai bekerja.

Bagaimanapun, cara Anda melakukannya, menyandikan string ke array byte dengan satu set karakter, dan kemudian mendekodekannya dengan yang lain, tidak akan berfungsi, seperti yang Anda lihat.

Dapatkah Anda memberi tahu kami lebih lanjut tentang dari mana string asli itu berasal, dan mengapa menurut Anda kode itu salah?

Lasse V. Karlsen
sumber
Itu datang langsung dari App.config dan saya pikir itu UTF8 secara default. Terima kasih!
Daniil Harik
Pengkodean file itu mungkin memengaruhi bagaimana file ditafsirkan, jadi saya akan melihatnya.
Lasse V. Karlsen
2
Perbaiki saya jika saya salah, tetapi pemahaman saya adalah bahwa, meskipun secara teknis "tidak dalam pengkodean tertentu", string .NET adalah larik byte yang sesuai persis dengan file UTF-16, byte untuk byte (tidak termasuk BOM). Ia bahkan menggunakan pengganti dengan cara yang sama (yang tampak seperti trik encoding). Tentu saja, Anda biasanya ingin menyimpan file sebagai UTF-8 tetapi memproses data dalam memori sebagai 16-bit. (Atau 32-bit, untuk menghindari kerumitan pasangan pengganti, meskipun saya tidak yakin apakah itu benar-benar layak.)
Jon Coombs
6

Sepertinya kode agak aneh. Untuk mendapatkan string dari aliran byte Utf8, yang perlu Anda lakukan adalah:

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

Jika Anda perlu menyimpan aliran iso-8859-1 byte ke suatu tempat, cukup gunakan: baris kode tambahan untuk sebelumnya:

byte[] iso88591data = Encoding.GetEncoding("ISO-8859-1").GetBytes(str);
Sander A
sumber
1
Ini jelas merupakan jawaban yang paling mudah. Masalah dalam kode memang bahwa penulis tampaknya berasumsi bahwa String di C # sudah dapat disimpan "menggunakan" pengkodean tertentu, yang tidak benar; mereka selalu UTF16 secara internal.
Nyerguds
1
Sangat setuju. Ketika Anda sudah memiliki UTF-16, cukup sulit untuk membuatnya menjadi pengkodean yang benar, karena ketika Anda mengonversi array byte menjadi string dengan pengkodean yang salah sudah ada informasi yang hilang.
Sander A
0

Baru saja menggunakan solusi Nathan dan berfungsi dengan baik. Saya perlu mengonversi ISO-8859-1 ke 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);
Nicolai Nita
sumber
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
sumber
-5

Berikut adalah contoh untuk 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
sumber