C # Dizeyi UTF-8'den ISO-8859-1'e (Latin1) H dönüştür


104

Bu konuyu Google'da araştırdım ve her cevaba baktım, ancak yine de anlamıyorum.

Temel olarak UTF-8 dizesini ISO-8859-1'e dönüştürmem gerekiyor ve bunu aşağıdaki kodu kullanarak yapıyorum:

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

Kaynak dizem

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

Ama ne yazık ki sonuç dizim

msg = "�ä�ö�õ�ü

Burada neyi yanlış yapıyorum?


5
.NET'teki tüm dizeler, dizeleri unicode karakterleri kullanarak dahili olarak depolar. String'in "windows-1252", "iso-8859-1", "utf-8", vb. Olduğuna dair bir fikir yoktur. Windows'ta temsili olmayan dizenizdeki karakterleri atmaya mı çalışıyorsunuz? -1252 kod sayfası?
Ian Boyd

1
@IanBoyd Aslında, String , sayılan UTF-16 kod birimleri dizisidir. (Ne yazık ki, Unicode terimi Encoding.UnicodeWin32 API içinde ve içinde yanlış uygulanmıştır . Unicode bir karakter kümesidir, kodlama değildir. UTF-16, Unicode için çeşitli kodlamalardan biridir.)
Tom Blodget

1
Yanlış eylem yaparsınız: utf8 kodlamasında bayt dizisi yaparsınız, ancak bunları iso kod çözme ile okursunuz. Kodlanmış sembollerle dizgi yapmak istiyorsanız, basit çağrı dizgisi msg = iso.GetString (iso.GetBytes (Message));
StuS

Buna Mojibake denir.
Rick James

Sanırım Daniil'in söylediği şey Message, UTF-8'den çözülmüş. Bu parçanın doğru çalıştığını varsayarsak, Latin-1'e dönüştürmek kadar basittir byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message). Ardından, StuS'un dediği gibi, Latin-1 baytları tekrar UTF-16'ya dönüştürebilirsinizEncoding.GetEncoding("ISO-8859-1").GetString(bytes)
Qwertie

Yanıtlar:


177

Hedef kodlamanızın kodunu çözmeyi denemeden önce bayt dizisini ayarlamak için Encoding.Convert kullanın .

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
Tek astarEncoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString)))

1
Dizeyi C # / .Net içinde kendiniz oluşturuyorsanız, bu kod% 100 doğru değildir, UTF-16'dan ("Unicode" değişkeni) kodlamanız gerekir. Çünkü bu varsayılandır. Bu yüzden yukarıdaki koddaki UTF8 Unicode olarak değiştirilmelidir.
2017,

Bunu kullanmanızı tavsiye ederim: Encoding iso = Encoding.GetEncoding ("ISO-8859-9"); Çünkü türkçe kodlama, Latince'den genişletilmiş tüm alfabeleri kapsar.
Fuat

27

Sanırım probleminiz, utf8 dizesini temsil eden baytların başka bir şey olarak yorumlandığında aynı dizeyle sonuçlanacağını varsaymanızdır (iso-8859-1). Ve bu sadece durum böyle değil. Joel spolsky'nin bu harika makalesini okumanızı tavsiye ederim .


1
Gerçekten ve espri anlayışı ile mükemmel bir makale! Bugün işte bir kodlama sorunuyla karşı karşıyaydım ve bu bana yardımcı oldu.
Pantelis

16

Bunu dene:

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

neden aynı utf-8 mesajını alıyorum? mesaj yerine string mesajını geçtim = <name> sdjfhsjdf </name>. sonra msg varieable.how'da latin verileri nasıl alınır?
user1237131

Bu benim için çalışıyor. System.Text ad alanını eklemeyi unutmayın.
Spawnrider

2
Encoding.Convert, dizede iso olmayan karakterler varsa dönüştürme sırasında geri dönüş istisnası atar
Tertium

8

İlk olarak dizenin kaynağını düzeltmeniz gerekir.

.

Bu dizeyi aldığınızda ve onu bir dizi bayta dönüştürdüğünüzde kodlama devreye girer.

Her halükarda, bunu yaptığınız şekilde, bir dizeyi bir karakter kümesiyle bir bayt dizisine kodlamak ve sonra onu başka bir karakterle çözmek, gördüğünüz gibi çalışmayacaktır.

Bize bu orijinal dizenin nereden geldiğini ve neden yanlış kodlandığını düşündüğünüzü anlatır mısınız?


Doğrudan App.config'den geliyor ve varsayılan olarak UTF8 olduğunu düşünüyordum. Teşekkür ederim!
Daniil Harik

Bu dosyanın kodlanması dosyanın yorumlanma şeklini etkileyebilir, bu yüzden ona bakardım.
Lasse V. Karlsen

2
Yanılıyorsam düzeltin, ancak benim anladığım kadarıyla teknik olarak "belirli bir kodlamada olmasa da" bir .NET dizesi, bayt için bayt (hariç) UTF-16 dosyasına tam olarak karşılık gelen bir bayt dizisidir ( BOM). Aynı şekilde vekilleri de kullanır (bu bir kodlama numarası gibi görünür). Tabii ki, genellikle dosyaları UTF-8 olarak depolamak, ancak hafızadaki verileri 16 bit olarak işlemek istersiniz. (Veya 32-bit, vekil çiftlerin karmaşıklığından kaçınmak için, bunun gerçekten mümkün olup olmadığından emin değilim.)
Jon Coombs

6

Biraz garip bir kod gibi görünüyor. Utf8 bayt akışından dize almak için yapmanız gereken tek şey:

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

İso-8859-1 bayt akışını bir yere kaydetmeniz gerekiyorsa, şunu kullanın: önceki için ek kod satırı:

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

1
Bu açıkça en basit cevaptır. Koddaki sorun aslında yazarın C # 'da bir String'in belirli bir kodlama "kullanılarak" depolanabileceğini varsayıyor gibi görünmesidir ki bu doğru değildir; bunlar her zaman dahili olarak UTF16'dır.
Nyerguds

1
Tamamen katılıyorum. Zaten UTF-16'ya sahipseniz, bunu doğru kodlamaya dönüştürmek oldukça zordur, çünkü bayt dizisini yanlış kodlamayla dizeye dönüştürdüğünüzde zaten bilgi kaybı vardır.
Sander A

0

Sadece Nathan'ın çözümünü kullandım ve iyi çalışıyor. ISO-8859-1'i Unicode'a dönüştürmem gerekiyordu:

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

İşte ISO-8859-9 için bir örnek;

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);}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.