2009-12-17 70 views
80

Tôi đã googled về chủ đề này và tôi đã xem xét mọi câu trả lời, nhưng tôi vẫn không hiểu.C# Chuyển đổi chuỗi từ UTF-8 sang ISO-8859-1 (Latin1) H

Về cơ bản tôi cần phải chuyển đổi UTF-8 chuỗi ISO-8859-1 và tôi làm điều đó bằng đoạn mã sau:

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

chuỗi nguồn của tôi là

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

Nhưng tiếc là chuỗi kết quả của tôi trở thành

msg = "�ä�ö�õ�ü 

Tôi đang làm gì sai ở đây?

+3

Tất cả các chuỗi trong .NET lưu trữ chuỗi bằng ký tự unicode. Không có khái niệm về một String là "windows-1252", "iso-8859-1", "utf-8", v.v. Bạn đang cố gắng vứt bỏ bất kỳ ký tự nào trong chuỗi của bạn mà không có biểu diễn trong Windows -1252 trang mã? –

+0

@IanBoyd Trên thực tế, một [String] (https://msdn.microsoft.com/en-us/library/system.string (v = vs.110) .aspx) là một chuỗi được đếm các đơn vị mã UTF-16. (Thật không may, thuật ngữ Unicode đã được áp dụng sai trong 'Encoding.Unicode' và trong API Win32. Unicode là một bộ ký tự, không phải là mã hóa. UTF-16 là một trong một số mã hóa cho Unicode.) –

+0

Bạn thực hiện hành động không chính xác: bạn tạo mảng byte trong mã hóa utf8, nhưng đọc chúng bằng giải mã iso. Nếu bạn muốn tạo chuỗi ký tự được mã hóa, nó gọi đơn giản ** string msg = iso.GetString (iso.GetBytes (Message)); ** – StuS

Trả lời

121

Sử dụng Encoding.Convert để điều chỉnh các mảng byte trước khi cố gắng để giải mã nó thành mã hóa đích.

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ớp lót một là 'Encoding.GetEncoding (" ISO-8859-1 "). GetString (Encoding.Convert (Encoding.UTF8, Encoding.GetEncoding (" ISO-8859-1 "), Encoding.UTF8.GetBytes (myString)))' –

+0

Nếu bạn đang tự tạo chuỗi trong C# /. Net, thì mã này không chính xác 100%, bạn cần mã hóa từ UTF-16 (đó là biến "Unicode"). Bởi vì đây là mặc định. Vì vậy, UTF8 trong đoạn mã trên phải được thay đổi thành Unicode. – goamn

7

Bạn cần sửa nguồn gốc của chuỗi ở địa điểm đầu tiên.

Một chuỗi trong .NET thực sự chỉ là một mảng gồm 16-bit mã unicode, các ký tự, vì vậy một chuỗi không nằm trong bất kỳ mã hóa cụ thể nào.

Đó là khi bạn lấy chuỗi đó và chuyển đổi nó thành một tập hợp các byte mã hóa đi vào hoạt động.

Trong mọi trường hợp, cách bạn đã làm, mã hóa chuỗi thành một mảng byte với một bộ ký tự và sau đó giải mã nó bằng một ký tự khác, sẽ không hoạt động, như bạn thấy.

Bạn có thể cho chúng tôi biết thêm về chuỗi gốc xuất phát từ đâu và tại sao bạn cho rằng chuỗi đó đã được mã hóa sai?

+0

Nó đến trực tiếp từ App.config và tôi đã nghĩ nó là UTF8 theo mặc định. Cảm ơn bạn! –

+0

Mã hóa của tệp đó có thể ảnh hưởng đến cách tệp được giải thích, vì vậy tôi sẽ xem xét tệp đó. –

+2

Sửa lỗi nếu tôi sai, nhưng sự hiểu biết của tôi là, trong khi về mặt kỹ thuật, nó không nằm trong bất kỳ mã hóa cụ thể nào, một chuỗi .NET là một mảng byte tương ứng chính xác với tệp UTF-16, byte cho byte (không bao gồm BOM). Nó thậm chí còn sử dụng thay thế theo cùng một cách (mà có vẻ như một thủ thuật mã hóa). Tất nhiên, bạn thường muốn lưu trữ các tệp dưới dạng UTF-8 nhưng xử lý dữ liệu trong bộ nhớ dưới dạng 16 bit. (Hoặc 32-bit, để tránh sự phức tạp của các cặp thay thế, mặc dù tôi không chắc chắn nếu điều đó thực sự khả thi.) –

19

Tôi nghĩ rằng vấn đề của bạn là bạn giả sử rằng các byte đại diện cho chuỗi utf8 sẽ dẫn đến cùng một chuỗi khi được hiểu là cái gì khác (iso-8859-1). Và đó chỉ đơn giản là không phải vậy. Tôi khuyên bạn nên đọc this excellent article bởi Joel spolsky.

+0

Cảm ơn bạn ... sẽ làm! –

+0

Bài viết tuyệt vời thực sự và với một cảm giác hài hước! Tôi đã phải đối mặt với một vấn đề mã hóa ngày hôm nay tại nơi làm việc và điều này đã giúp tôi. – Pantelis

14

Hãy thử điều này:

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

lý do tại sao tôi nhận được cùng một thông điệp utf-8 ở vị trí của thông điệp tôi đã thông qua chuỗi tin nhắn = sdjfhsjdf .có cùng một đầu ra nhận được trong msg varieable.how để có được dữ liệu latin? – user1237131

+0

Điều này phù hợp với tôi. Hãy nhớ bao gồm không gian tên System.Text. – Spawnrider

+2

Encoding.Convert ném ngoại lệ dự phòng trong khi chuyển đổi nếu chuỗi có ký tự không phải là ISO – Tertium

4

Có vẻ như mã lạ. Để có được chuỗi từ UTF8 byte stream tất cả các bạn cần làm là:

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

Nếu bạn cần phải lưu dòng byte iso-8859-1 đến một nơi nào đó chỉ cần sử dụng: thêm dòng mã cho trước:

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

Đây rõ ràng là câu trả lời đơn giản nhất. Vấn đề trong mã thực sự là tác giả dường như giả định rằng một String trong C# có thể đã được lưu trữ "bằng cách sử dụng" một mã hóa nhất định, mà chỉ đơn giản là không đúng; chúng luôn là UTF16 trong nội bộ. – Nyerguds

+1

Hoàn toàn đồng ý. Khi bạn đã có UTF-16, nó là khá khó để làm cho rằng vào mã hóa chính xác, bởi vì khi bạn chuyển đổi mảng byte thành chuỗi với mã hóa sai có đã mất thông tin. –

0

Chỉ cần sử dụng giải pháp của Nathan và nó hoạt động tốt. Tôi cần thiết để chuyển đổi tiêu chuẩn ISO-8859-1 sang 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

Đây là một mẫu cho tiêu chuẩn 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);} 
Các vấn đề liên quan