C#将字符串从UTF-8转换为ISO-8859-1(Latin1)H


103

我已经用谷歌搜索了这个话题,并且已经查看了所有答案,但还是不明白。

基本上,我需要将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 = "�ä�ö�õ�ü

我在这里做错了什么?


5
.NET中的所有字符串都在内部使用Unicode字符存储字符串。没有字符串的概念是“ windows-1252”,“ iso-8859-1”,“ utf-8”等。您是否要丢弃字符串中没有Windows表示形式的任何字符? -1252代码页?
伊恩·博伊德

1
@IanBoyd实际上,字符串是UTF-16代码单元的计数序列。(不幸的是,Encoding.Unicode在Win32 API 中和Win32 API中都误用了Unicode术语。Unicode 是字符集,而不是编码。UTF-16是Unicode的几种编码之一。)
Tom Blodget

1
您执行了错误的操作:您使用utf8编码制作了字节数组,但是通过iso解码读取了它们。如果要使用编码的符号生成字符串,则可以简单地调用字符串msg = iso.GetString(iso.GetBytes(Message));
StuS

那就是Mojibake。
瑞克·詹姆斯

我猜Daniil所说的是Message从UTF-8解码而来的。假设该部分正常工作,则转换为Latin-1就像一样简单byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message)。然后,就像StuS所说的那样,您可以使用Encoding.GetEncoding("ISO-8859-1").GetString(bytes)
Qwertie

Answers:


176

在尝试将其解码为目标编码之前,请使用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);

7
一个班轮是Encoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString)))

1
如果要在C#/。Net中自己创建字符串,则此代码不是100%正确,因此您需要使用UTF-16(即变量“ Unicode”)进行编码。因为这是默认设置。因此,上面代码中的UTF8必须更改为Unicode。
goamn

我建议使用此方法:Encoding iso = Encoding.GetEncoding(“ ISO-8859-9”); 因为土耳其语编码几乎涵盖了所有拉丁文字母。
Fuat

26

我认为您的问题是,您假设代表utf8字符串的字节在解释为其他内容时会产生相同的字符串(iso-8859-1)。事实并非如此。我建议您阅读Joel spolsky撰写的精彩文章


1
的确是出色的文章,带有幽默感!今天我在工作中遇到编码问题,这对我有所帮助。
Pantelis 2012年

16

试试这个:

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

为什么我收到相同的utf-8消息?代替我通过字符串message = <name> sdjfhsjdf </ name>传递的消息。然后在msg varieable.how中获取相同的输出?
user1237131 2013年

这对我有用。记住要包括System.Text命名空间。
Spawnrider 2013年

2
Encoding.Convert在字符串包含非ISO字符时进行转换时抛出回退异常
Tertium 2014年

8

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

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

就是当您采用该字符串并将其转换为一组字节时,编码才起作用。

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

您能否告诉我们更多有关原始字符串的来源以及为什么您认为其编码错误的信息?


它直接来自App.config,我在默认情况下认为它是UTF8。谢谢!
丹尼尔·哈里克

该文件的编码可能会影响文件的解释方式,所以我来看看。
Lasse V. Karlsen

2
请纠正我,如果我错了,但是我的理解是,尽管从技术上讲它“不是任何特定的编码”,.NET字符串是一个字节数组,它精确地对应于UTF-16文件,一个字节一个字节(不包括) BOM)。它甚至以相同的方式使用代理(这似乎是一种编码技巧)。当然,您通常希望将文件存储为UTF-8,但将内存中的数据处理为16位。(或32位,以避免代理对的复杂性,尽管我不确定这是否真的可行。)
Jon Coombs 2013年

6

似乎有点奇怪的代码。要从Utf8字节流中获取字符串,您需要做的是:

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

如果需要将iso-8859-1字节流保存到某个地方,则只需使用:前面的其他代码行:

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

1
显然,这是最直接的答案。代码中的问题确实是作者似乎认为C#中的String已经可以“使用”某种编码来存储,这根本不是事实。他们内部始终是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 = "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);}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.