如何在C#中将字符串转换为UTF-8?

193

我从第三方应用程序接收到一个字符串,但由于编码不正确,我的一部分字符串在西班牙语中看起来像这样:

Acción

而它应该是这个样子的:

Acción

根据这个问题的答案:How to know string encoding in C#,我接收的编码应该已经是UTF-8的,但实际上却被读取成了Encoding.Default(可能是ANSI?)。

我正在尝试将此字符串转换为真正的UTF-8,但其中一个问题是我只能看到Encoding类的一个子集(仅有UTF8和Unicode属性),可能是因为我受限于Windows Surface API。

我已经尝试了一些在互联网上找到的代码片段,但到目前为止没有一个适用于东方语言(例如韩语)的成功示例。

var utf8 = Encoding.UTF8;
byte[] utfBytes = utf8.GetBytes(myString);
myString= utf8.GetString(utfBytes, 0, utfBytes.Length);     

我也尝试将字符串提取为字节数组,然后使用 UTF8.GetString:

byte[] myByteArray = new byte[myString.Length];
for (int ix = 0; ix < myString.Length; ++ix)
{
    char ch = myString[ix];
    myByteArray[ix] = (byte) ch;
}

myString = Encoding.UTF8.GetString(myByteArray, 0, myString.Length);

你们有没有其他的想法我可以尝试一下?


5
你的问题来自于最初创建字符串的代码(可能是从流或字节数组中创建)。请展示那段代码。 - SLaks
1
@Oded:.Net字符串在内存中以UTF16格式存储,但是Encoding.Default返回系统的ANSI代码页。 - SLaks
这是一个在英语环境下无法正常工作的字符串示例:我的前端应用程序显示的是“day’s”,而不是“day's”。 - Gaara
7个回答

324

如您所知,该字符串是用 Encoding.Default 编码的,您可以简单地使用以下代码:

byte[] bytes = Encoding.Default.GetBytes(myString);
myString = Encoding.UTF8.GetString(bytes);

还有一件事你需要记住:如果你使用Console.WriteLine输出一些字符串,那么你也应该写上Console.OutputEncoding = System.Text.Encoding.UTF8;!!! 不然所有的utf8字符串将会以gbk的形式输出...


4
尝试使用 Encoding.GetEncoding(...);你需要查找实际使用错误编码的名称。 - SLaks
我们从世界各地收到崩溃报告,并将其插入到一个UTF8数据库中。当我尝试插入一些来自欧洲的崩溃报告时,我遇到了编码错误。这个转换使得报告得以插入。非常感谢。 - Adam Bruss
提示:如果您使用Console.WriteLine输出一些字符串,则还应编写*Console.OutputEncoding = System.Text.Encoding.UTF8;*!否则,所有utf8字符串都将输出为gbk... - ch271828n
1
你能解释一下为什么这样能行吗?如果默认编码是GB2312,那么Encoding.Default.GetBytes将会使用GB2312编码器将字符串编码成字节数组,然后Encoding.UTF8.GetString将尝试使用UTF8解码器解码字节数组,结果应该是错误的,但为什么它能正常工作呢?@anothershrubery - guorongfei
2
@guorongfei 假设 myString 是乱码。该代码首先撤销错误解码,然后进行正确解码。只要错误解码没有丢失数据,它就能正常工作。但正如 @SLaks 指出的那样,最好使用确切的错误编码。 (在代码中使用更好的名称和注释有助于理解看起来非常错误的代码实际上是试图做正确的事情。) - Tom Blodget
显示剩余6条评论

24
string utf8String = "Acción";
string propEncodeString = string.Empty;

byte[] utf8_Bytes = new byte[utf8String.Length];
for (int i = 0; i < utf8String.Length; ++i)
{
   utf8_Bytes[i] = (byte)utf8String[i];
}

propEncodeString = Encoding.UTF8.GetString(utf8_Bytes, 0, utf8_Bytes.Length);

输出应该看起来像

Acción

day’s显示 day's

调用 DecodeFromUtf8();

private static void DecodeFromUtf8()
{
    string utf8_String = "day’s";
    byte[] bytes = Encoding.Default.GetBytes(utf8_String);
    utf8_String = Encoding.UTF8.GetString(bytes);
}

1
谢谢!它在西班牙语中可以工作,问题是同样的东西在东方语言(例如韩语)中不起作用。我正在尝试在互联网上寻找8位到UTF-8转换算法,但仍然没有运气。 - Gaara
这是一个字符串不适用于英语的例子: 我的前端应用程序显示 day’s 而不是 day's。 - Gaara
好的,让我试着搞一下看看能得出什么结果。 - MethodMan
我测试了一下,它返回了日期。我将粘贴我测试过的静态方法,它与@anothershrubery提供的实际上是相同的。 - MethodMan
你可以通过传递DecodeFromUtf8(string utf8string)来改变该方法。 - MethodMan

13
您的代码正在读取一系列UTF8编码的字节,并使用8位编码进行解码。
您需要修复该代码以使用UTF8对字节进行解码。
或者(不理想),您可以将坏字符串转换回原始字节数组,通过使用错误的编码对其进行编码,然后重新将字节解码为UTF8。

谢谢!问题在于第三方应用程序是C ++,而我的代码是C#,所以我想解码发生在这两者之间的“桥梁”中。 - Gaara

10
 Encoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(mystring));

10

@anothershrubery的回答对我有用。我使用了StringEntensions Class进行了增强,因此我可以轻松地在我的程序中转换任何字符串。

方法:

public static class StringExtensions
{
    public static string ToUTF8(this string text)
    {
        return Encoding.UTF8.GetString(Encoding.Default.GetBytes(text));
    }
}

使用方法:

string myString = "Acción";
string strConverted = myString.ToUTF8();

或者简单地说:
string strConverted = "Acción".ToUTF8();

5

如果您想将任何字符串保存到MySQL数据库中,请执行以下操作:

1)您的数据库字段结构应该设置为utf8-general-ci(在phpMyAdmin或其他控制面板中)。

2)您需要将字符串[例如textbox1.text]更改为字节,因此:

2-1)定义byte[] st2;

2-2)通过以下方式将您的字符串[textbox1.text]转换为Unicode [多字节字符串]:

byte[] st2 = System.Text.Encoding.UTF8.GetBytes(textBox1.Text);

3) 在查询之前执行此 SQL 命令:

string mysql_query2 = "SET NAMES 'utf8'";
cmd.CommandText = mysql_query2;
cmd.ExecuteNonQuery();

3-2) 现在,您应该通过以下方式将此值插入到例如名称字段中:

cmd.CommandText = "INSERT INTO customer (`name`) values (@name)";

4) 许多解决方案忽略了以下主要任务: 在命令参数中,您应该使用addwithvalue而不是add,如下所示:

cmd.Parameters.AddWithValue("@name",ut);

享受真实的数据,而不是在您的数据库服务器中出现问题。


3
使用以下代码段从CSV文件中获取字节:
protected byte[] GetCSVFileContent(string fileName)
    {
        StringBuilder sb = new StringBuilder();
        using (StreamReader sr = new StreamReader(fileName, Encoding.Default, true))
        {
            String line;
            // Read and display lines from the file until the end of 
            // the file is reached.
            while ((line = sr.ReadLine()) != null)
            {
                sb.AppendLine(line);
            }
        }
        string allines = sb.ToString();


        UTF8Encoding utf8 = new UTF8Encoding();


        var preamble = utf8.GetPreamble();

        var data = utf8.GetBytes(allines);


        return data;
    }

请拨打以下电话并将其保存为附件

           Encoding csvEncoding = Encoding.UTF8;
                   //byte[] csvFile = GetCSVFileContent(FileUpload1.PostedFile.FileName);
          byte[] csvFile = GetCSVFileContent("Your_CSV_File_NAme");


        string attachment = String.Format("attachment; filename={0}.csv", "uomEncoded");

        Response.Clear();
        Response.ClearHeaders();
        Response.ClearContent();
        Response.ContentType = "text/csv";
        Response.ContentEncoding = csvEncoding;
        Response.AppendHeader("Content-Disposition", attachment);
        //Response.BinaryWrite(csvEncoding.GetPreamble());
        Response.BinaryWrite(csvFile);
        Response.Flush();
        Response.End();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接