Làm cách nào để chuyển đổi chuỗi thành UTF-8 trong C #?


146

Tôi có một chuỗi mà tôi nhận được từ ứng dụng của bên thứ ba và tôi muốn hiển thị chính xác chuỗi đó bằng bất kỳ ngôn ngữ nào sử dụng C # trên Windows Surface của tôi.

Do mã hóa không chính xác, một đoạn trong chuỗi của tôi trông như thế này bằng tiếng Tây Ban Nha:

Chính phủ

trong khi nó sẽ trông như thế này:

Acción

Theo câu trả lời cho câu hỏi này: Làm thế nào để biết mã hóa chuỗi trong C # , mã hóa tôi đang nhận phải có trên UTF-8, nhưng nó được đọc trên Encoding.Default (có lẽ là ANSI?).

Tôi đang cố gắng chuyển đổi chuỗi này thành UTF-8 thực sự, nhưng một trong những vấn đề là tôi chỉ có thể thấy một tập hợp con của lớp Mã hóa (chỉ thuộc tính UTF8 và Unicode), có lẽ vì tôi bị giới hạn trong API bề mặt của windows.

Tôi đã thử một số đoạn mà tôi tìm thấy trên internet, nhưng không ai trong số họ đã chứng minh thành công cho đến nay đối với các ngôn ngữ phương Đông (tức là tiếng Hàn). Một ví dụ như sau:

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

Tôi cũng đã thử trích xuất chuỗi thành một mảng byte và sau đó sử dụng 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);

Các bạn có ý tưởng nào khác mà tôi có thể thử không?


5
Vấn đề của bạn đến từ mã đã tạo chuỗi (từ luồng hoặc byte []) ở vị trí đầu tiên. Vui lòng hiển thị mã đó.
SLaks

1
@Oded: Chuỗi .Net được lưu trữ trong bộ nhớ dưới dạng UTF16, nhưng Encoding.Defaulttrả về bảng mã ANSI của hệ thống.
SLaks

Dưới đây là một ví dụ về chuỗi không hoạt động với ngôn ngữ tiếng Anh: thay vì hiển thị ngày, ứng dụng giao diện người dùng của tôi đang hiển thị: dayâ €
Gaara

Câu trả lời:


251

Như bạn biết chuỗi đang đến vì Encoding.Defaultbạn có thể chỉ cần sử dụng:

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

Một điều khác bạn có thể phải nhớ: Nếu bạn đang sử dụng Console.WriteLine để xuất một số chuỗi, thì bạn cũng nên viết Console.OutputEncoding = System.Text.Encoding.UTF8;!!! Hoặc tất cả các chuỗi utf8 sẽ được xuất ra dưới dạng gbk ...


Điều này cũng hoạt động, nó thực sự đẹp hơn nhiều so với câu trả lời của tôi, nó cũng hoạt động. Tôi đang cho bạn một công việc tuyệt vời +1
Phương thức

Cảm ơn! Vấn đề là, như tôi đã đề cập trong phần mô tả, API cho bề mặt không đầy đủ (không có Encoding.Default cho tôi).
Gaara

3
@Gaara: Hãy thử Encoding.GetEncoding(...); bạn sẽ cần tìm tên của mã hóa thực tế được sử dụng không chính xác ở đầu kia.
SLaks

1
bạn có thể giải thích tại sao điều này làm việc? nếu Mặc định là GB2312, thì Encoding.Default.GetBytes sẽ mã hóa chuỗi thành mảng byte sử dụng bộ mã hóa GB2312, sau đó Encoding.UTF8.GetString sẽ cố gắng giải mã mảng byte sử dụng bộ giải mã UTF8, nhưng kết quả sẽ sai. @anothershrubery
guorongfei

1
@guorongfei Tiền đề myStringlà mojibake. Mã đầu tiên hoàn tác giải mã sai sau đó thực hiện giải mã đúng. Nó hoạt động miễn là giải mã sai không bị mất dữ liệu. Nhưng như @SLaks đã chỉ ra, sẽ tốt hơn nếu sử dụng mã hóa chính xác sai. (Tên và nhận xét tốt hơn trong mã sẽ giúp hiểu được mã trông rất sai thực sự là một nỗ lực làm đúng.)
Tom Blodget

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

Đầu ra sẽ giống như

Acción

ngày hiển thị ngày

gọi DecodeFromUtf8 ();

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

1
Cảm ơn! Nó hoạt động với tiếng Tây Ban Nha, vấn đề là điều tương tự sẽ không hoạt động với các ngôn ngữ phương Đông (tức là tiếng Hàn). Tôi đang cố gắng tìm kiếm thuật toán chuyển đổi 8 bit sang UTF-8 trên internet, nhưng vẫn không gặp may.
Gaara

Dưới đây là một ví dụ về chuỗi không hoạt động với ngôn ngữ tiếng Anh: thay vì hiển thị ngày, ứng dụng giao diện người dùng của tôi đang hiển thị: dayâ €
Gaara

ok hãy để tôi
loay hoay

Tôi đã thử nghiệm và nó trả về ngày tôi sẽ dán phương thức tĩnh mà tôi đã thử nghiệm nó thực sự giống như những gì @anothershrubery đã cung cấp
Phương thức quản lý

bạn có thể thay đổi phương thức đó bằng cách chuyển DecodeFromUtf8 (chuỗi utf8 chuỗi);
Phương thức quản lý

12

Mã của bạn đang đọc một chuỗi các byte được mã hóa UTF8 và giải mã chúng bằng mã hóa 8 bit.

Bạn cần sửa mã đó để giải mã các byte là UTF8.

Ngoài ra ( không lý tưởng ), bạn có thể chuyển đổi chuỗi xấu trở lại mảng byte ban đầu bằng cách mã hóa nó bằng cách sử dụng mã hóa không chính xác, sau đó giải mã lại các byte thành UTF8.


Cảm ơn! Vấn đề là ứng dụng của bên thứ ba là C ++, trong khi mã của tôi là C #, vì vậy tôi đoán việc giải mã xảy ra trong "cầu nối" giữa hai thứ đó.
Gaara


5

Nếu bạn muốn lưu bất kỳ chuỗi nào vào cơ sở dữ liệu mysql, hãy làm điều này: ->

Cấu trúc trường cơ sở dữ liệu của bạn i phpmyadmin [hoặc bất kỳ bảng điều khiển nào khác] nên được đặt thành utf8-gerneral-ci

2) bạn nên thay đổi chuỗi của mình [Ví dụ: textbox1.text] thành byte, do đó

2-1) xác định byte [] st2;

2-2) chuyển đổi chuỗi [textbox1.text] của bạn thành unicode [chuỗi mmultibyte] bằng cách:

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

3) thực hiện lệnh sql này trước bất kỳ truy vấn nào:

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

3-2) bây giờ bạn nên chèn giá trị này vào ví dụ trường tên bằng cách:

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

4) công việc chính mà nhiều giải pháp không chú ý đến đó là dòng dưới đây: bạn nên sử dụng addwithvalue thay vì thêm tham số lệnh như dưới đây:

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

+++++++++++++++++++++++++++++++++++ tận hưởng dữ liệu thực trong máy chủ cơ sở dữ liệu của bạn thay vì ????


3

Sử dụng đoạn mã dưới đây để lấy byte từ tệp 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;
    }

Gọi bên dưới và lưu nó dưới dạng tệp đính kèm

           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();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.