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

Posted

技术标签:

【中文标题】C# 将字符串从 UTF-8 转换为 ISO-8859-1 (Latin1) H【英文标题】:C# Convert string from UTF-8 to ISO-8859-1 (Latin1) H 【发布时间】:2010-12-27 16:33:43 【问题描述】:

我已经用谷歌搜索了这个主题,并且查看了每个答案,但我仍然不明白。

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

我在这里做错了什么?

【问题讨论】:

.NET 中的所有字符串都使用 unicode 字符在内部存储字符串。没有字符串是“windows-1252”、“iso-8859-1”、“utf-8”等的概念。您是否试图丢弃字符串中没有在 Windows 中表示的任何字符-1252 代码页? @IanBoyd 实际上,String 是 UTF-16 代码单元的计数序列。 (不幸的是,Unicode 一词在Encoding.Unicode 和 Win32 API 中被误用。Unicode 是一种字符集,而不是一种编码。UTF-16 是 Unicode 的几种编码之一。) 你做了不正确的动作:你用utf8编码制作字节数组,但通过iso解码读取它们。如果你想用编码符号制作字符串,只需调用 string msg = iso.GetString(iso.GetBytes(Message)); 那叫 Mojibake。 我猜 Daniil 的意思是 Message 是从 UTF-8 解码的。假设该部分工作正常,转换为 Latin-1 就像 byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(Message) 一样简单。然后,就像 StuS 所说,您可以使用 Encoding.GetEncoding("ISO-8859-1").GetString(bytes) 将 Latin-1 字节转换回 UTF-16 【参考方案1】:

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

【讨论】:

一班人是Encoding.GetEncoding("ISO-8859-1").GetString(Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(myString))) 如果您在 C#/.Net 中自己创建字符串,那么此代码不是 100% 正确的,您需要从 UTF-16(即变量“Unicode”)进行编码。因为这是默认设置。所以上面代码中的UTF8必须改成Unicode。 我推荐使用这个:Encoding iso = Encoding.GetEncoding("ISO-8859-9");因为土耳其语编码几乎涵盖了从拉丁语扩展而来的所有字母。 你知道,isoBytes 也只是iso.GetBytes(Message);。这里不需要转换任何东西。事实上,你可以跳过所有这些并说string msg = Message任何这些转换都没有真正意义,因为开始和结束都只是一个 .Net String。只要您不需要将其作为字节处理,文本编码在 .Net String 上是无关紧要的。【参考方案2】:

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

【讨论】:

确实是优秀的文章,带有幽默感!我今天在工作中遇到了编码问题,这帮助了我。【参考方案3】:

试试这个:

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=sdjfhsjdf。然后在 msg 变量中获得相同的输出。如何获取拉丁数据? 这对我有用。记得包含 System.Text 命名空间。 Encoding.Convert 在转换时抛出回退异常,如果字符串包含非 iso 字符【参考方案4】:

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

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

当您将该字符串转换为一组字节时,编码开始发挥作用。

在任何情况下,如您所见,您使用一种字符集将字符串编码为字节数组,然后使用另一个字符集对其进行解码的方式都行不通。

您能告诉我们更多关于原始字符串的来源,以及您认为它编码错误的原因吗?

【讨论】:

它直接来自 App.config,我认为它默认是 UTF8。谢谢! 该文件的编码可能会影响文件的解释方式,所以我会看看。 如果我错了,请纠正我,但我的理解是,虽然从技术上讲它“没有任何特定的编码”,但 .NET 字符串是一个字节数组,它精确对应于 UTF- 16 个文件,逐字节(不包括 BOM)。它甚至以相同的方式使用代理(这似乎是一种编码技巧)。当然,您通常希望将文件存储为 UTF-8,但将内存中的数据处理为 16 位。 (或 32 位,以避免代理对的复杂性,尽管我不确定这是否真的可行。) @JonCoombs 我不认为这是正确的。 UTF-16 适用于扩展操作码。 .Net 字符串仅使用 16 位代码点数组,没有任何扩展。据我所知,它只支持 0000-FFFF 范围。【参考方案5】:

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

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

如果您需要将 iso-8859-1 字节流保存到某个地方,那么只需使用: 前面的附加代码行:

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

【讨论】:

这显然是最直接的答案。代码中的问题确实是作者似乎假设 C# 中的字符串已经可以“使用”某种编码来存储,这根本不是真的;它们在内部始终是 UTF16。 完全同意。当您已经拥有 UTF-16 时,很难将其转换为正确的编码,因为当您将字节数组转换为编码错误的字符串时,已经丢失了信息。【参考方案6】:

刚刚使用了 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);

【讨论】:

【参考方案7】:
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);

【讨论】:

【参考方案8】:

或许能帮上忙 将一个代码页转换为另一个:

    public static string fnStringConverterCodepage(string sText, string sCodepageIn = "ISO-8859-8", string sCodepageOut="ISO-8859-8")
    
        string sResultado = string.Empty;
        try
        
            byte[] tempBytes;
            tempBytes = System.Text.Encoding.GetEncoding(sCodepageIn).GetBytes(sText);
            sResultado = System.Text.Encoding.GetEncoding(sCodepageOut).GetString(tempBytes);
        
        catch (Exception)
        
            sResultado = "";
        
        return sResultado;
    

用法:

string sMsg = "ERRO: Não foi possivel acessar o servico de Autenticação";
var sOut = fnStringConverterCodepage(sMsg ,"ISO-8859-1","UTF-8"));

输出:

"Não foi possivel acessar o servico de Autenticação"

【讨论】:

【参考方案9】:

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

【讨论】:

以上是关于C# 将字符串从 UTF-8 转换为 ISO-8859-1 (Latin1) H的主要内容,如果未能解决你的问题,请参考以下文章

C# WINFORM ,如何将一个中文字符串转换成UTF-8

将 XML 字符串 API 响应转换为键值对象 C#

如何使用c#将xml字符串转换为对象

将字符串从 UTF-8 转换为 ISO-8859-1

需要帮助将字符串从 c++ 转换为 c# 格式

c# byte数组转string