2009-12-17 39 views
80

我已经使用了这个主题,我已经看过每个答案,但我仍然不明白。C#将字符串从UTF-8转换为ISO-8859-1(Latin1)H

基本上我需要UTF-8字符串转换为ISO-8859-1和我使用下面的代码它:

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

我的源字符串是

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

但不幸的是我的结果字符串变成

msg = "�ä�ö�õ�ü 

我在做什么错在这里?

+3

.NET中的所有字符串都使用unicode字符在内部存储字符串。没有一个字符串的概念是“windows-1252”,“iso-8859-1”,“utf-8”等。你是否试图抛弃字符串中没有Windows中的表示的任何字符-1252代码页? –

+0

@IanBoyd实际上,一个[String](https://msdn.microsoft.com/en-us/library/system.string(v = vs.110).aspx)是一个统计的UTF-16代码单元序列。 (不幸的是,术语Unicode在'Encoding.Unicode'和Win32 API中被误用了.Unicode是一个字符集,而不是编码。UTF-16是Unicode的几种编码之一。) –

+0

你做出不正确的操作:你以utf8编码制作字节数组,但通过iso解码读取它们。如果你想让编码符号的字符串,它简单地调用** string msg = iso.GetString(iso.GetBytes(Message)); ** – StuS

回答

121

使用Encoding.Convert在尝试将其解码到你的目的地编码前调整字节数组。

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

单行是'Encoding.GetEncoding(“ISO-8859-1”)。GetString(Encoding.Convert(Encoding.UTF8,Encoding.GetEncoding(“ ISO-8859-1“),Encoding.UTF8.GetBytes(myString)))' – 2015-12-11 15:35:05

+0

如果你在C#/ .Net中自己创建字符串,那么这个代码不是100%正确的,你需要从UTF-16编码(这是变量“Unicode”)。因为这是默认设置。所以上面的代码中的UTF8必须更改为Unicode。 – goamn

7

您需要首先修复字符串的来源。

.NET中的字符串实际上只是一个16位unicode代码点(字符)的数组,因此字符串不是以任何特定的编码。

这是当你把该字符串,并将其转换为编码进场的一组字节。

在任何情况下,如您所见,将字符串编码为具有一个字符集的字节数组,然后使用另一个字符集对其解码,将无法正常工作。

你能告诉我们更多关于原始字符串来自哪里的原因,以及为什么你认为它被编码错了?

+0

它直接来自App.config,我认为它默认是UTF8。谢谢! –

+0

该文件的编码可能会影响文件被解释的方式,所以我会看一下。 –

+2

纠正我,如果我错了,但我的理解是,虽然技术上它“没有在任何特定的编码”,一个.NET字符串是一个字节数组,恰好对应于一个UTF-16文件,字节的字节不包括物料清单)。它甚至以同样的方式使用代理(这看起来像编码技巧)。当然,您通常希望将文件存储为UTF-8,但将数据作为16位处理内存。 (或32位,以避免代理对的复杂性,尽管我不确定这是否真的可行。) –

19

我认为你的问题是,你认为代表utf8字符串的字节在被解释为别的东西时会导致相同的字符串(iso-8859-1)。而那根本就不是这样。我建议你阅读Joel spolsky的this excellent article

+0

谢谢你...会做! –

+0

非常棒的文章,幽默感!今天我在工作中遇到了一个编码问题,这帮助我解决了问题。 – Pantelis

14

试试这个:

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

为什么我得到相同的utf-8消息?代替消息我通过字符串消息= sdjfhsjdf。然后获得相同的输出msg varieable.how获取拉丁数据? – user1237131

+0

这对我有用。请记住包含System.Text命名空间。 – Spawnrider

+2

Encoding.Convert抛出后备异常,同时转换字符串是否具有非iso字符 – Tertium

4

似乎有点奇怪的代码。为了从UTF8字节流中的所有你需要做的得到的字符串是:

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

如果需要ISO-8859-1字节流保存到某个地方,然后只需使用:代码为先前 附加行:

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

这显然是最直接的答案。代码中的问题确实是作者似乎认为C#中的字符串已经可以“使用”某种编码进行存储了,这根本不是真的;他们内部始终是UTF16。 – Nyerguds

+1

完全同意。当你已经有了UTF-16编码时,很难将其编码为正确的编码,因为当你将字节数组转换为错误编码的字符串时,信息已经丢失。 –

0

刚刚使用了Nathan的解决方案,它工作正常。我需要ISO-8859-1转换为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

这里是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);}