ฉันจะแปลงสตริงเป็น UTF-8 ใน C # ได้อย่างไร


146

ฉันมีสตริงที่ฉันได้รับจากแอพของบุคคลที่สามและฉันต้องการแสดงอย่างถูกต้องในภาษาใด ๆ โดยใช้ C # บน Windows Surface ของฉัน

เนื่องจากการเข้ารหัสที่ไม่ถูกต้องส่วนหนึ่งของสตริงของฉันมีลักษณะเช่นนี้ในภาษาสเปน:

Acción

ในขณะที่ควรมีลักษณะเช่นนี้:

Acción

ตามคำตอบของคำถามนี้: จะรู้ได้อย่างไรว่าการเข้ารหัสสตริงใน C #การเข้ารหัสที่ฉันได้รับควรมาที่ UTF-8 แล้ว แต่มันถูกอ่านใน Encoding.Default (อาจเป็น ANSI)

ฉันกำลังพยายามแปลงสตริงนี้เป็น UTF-8 จริง แต่ปัญหาอย่างหนึ่งคือฉันเห็นเฉพาะเซ็ตย่อยของคลาสการเข้ารหัส (คุณสมบัติ UTF8 และ Unicode เท่านั้น) อาจเป็นเพราะฉัน จำกัด Windows window 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 strings ถูกเก็บไว้ในหน่วยความจำในรูปแบบ UTF16 แต่Encoding.Defaultจะส่งกลับANEP codepage ของระบบ
SLaks

นี่คือตัวอย่างของสตริงที่ไม่สามารถใช้กับภาษาอังกฤษได้: แทนที่จะแสดงวันแอพพลิเคชั่นส่วนหน้าของฉันแสดง: day’ s
Gaara

คำตอบ:


251

ดังที่คุณทราบว่าสายอักขระเข้ามาในแบบที่Encoding.Defaultคุณสามารถใช้

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

อีกสิ่งที่คุณอาจต้องจำไว้: ถ้าคุณใช้ Console.WriteLine เพื่อเอาท์พุทสตริงคุณก็ควรเขียนConsole.OutputEncoding = System.Text.Encoding.UTF8;!!! หรือสตริง utf8 ทั้งหมดจะถูกส่งออกเป็น gbk ...


มันใช้งานได้ดีกว่าคำตอบของฉันจริง ๆ ซึ่งดีกว่าฉันยังให้ผล +1 ที่ยอดเยี่ยมแก่คุณอีกด้วย
MethodMan

ขอบคุณ! ปัญหาคือว่าตามที่ฉันกล่าวถึงในคำอธิบาย API สำหรับพื้นผิวไม่สมบูรณ์ (ไม่มีการเข้ารหัสเริ่มต้นสำหรับฉัน)
กาอาระ

3
@Garaara: ลองEncoding.GetEncoding(...); คุณจะต้องค้นหาชื่อของการเข้ารหัสจริงที่ใช้อย่างไม่ถูกต้องที่ปลายอีกด้าน
slaks

1
คุณอธิบายได้ไหมว่าทำไมสิ่งนี้ถึงได้ผล หากค่าเริ่มต้นคือ GB2312 จากนั้นการเข้ารหัสค่าเริ่มต้น GetBytes จะเข้ารหัสสตริงไปยังไบต์อาร์เรย์ใช้ตัวเข้ารหัส GB2312 จากนั้นการเข้ารหัส UTF8.GetString จะพยายามถอดรหัสอาร์เรย์ไบต์ใช้ตัวถอดรหัส UTF8 ผลลัพธ์จะผิด @anothershrubery
guorongfei

1
@guorongfei หลักฐานmyStringคือ mojibake รหัสก่อนจะยกเลิกการถอดรหัสผิดจากนั้นทำการถอดรหัสที่ถูกต้อง มันทำงานได้ตราบใดที่การถอดรหัสผิดไม่ทำให้ข้อมูลสูญหาย แต่เมื่อ @SLaks ชี้ให้เห็นว่าการใช้การเข้ารหัสที่ผิดนั้นดีกว่า (ชื่อและความคิดเห็นที่ดีขึ้นในรหัสจะช่วยในการทำความเข้าใจว่ารหัสที่ดูผิด ๆ นั้นจริง ๆ แล้วเป็นความพยายามในการทำสิ่งที่ถูกต้อง)
Tom Blodget

18
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 แสดงวัน

โทร 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 ในอินเทอร์เน็ต แต่ก็ยังไม่มีโชค
กาอาระ

นี่คือตัวอย่างของสตริงที่ไม่สามารถใช้กับภาษาอังกฤษได้: แทนที่จะแสดงวันแอพพลิเคชั่นส่วนหน้าของฉันแสดง: day’ s
Gaara

ตกลงให้ฉันยุ่งกับมันและดูว่าฉันจะเกิดอะไรขึ้นกับ
เมธอด Man

ฉันทดสอบแล้วและคืนค่าวันที่ฉันจะวางวิธีแบบคงที่ที่ฉันทดสอบจริง ๆ แล้วเป็นเช่นเดียวกับที่ @anothershrubery ให้ไว้
MethodMan

คุณสามารถเปลี่ยนวิธีการนั้นได้โดยผ่าน DecodeFromUtf8 (สตริง utf8string)
เมธอด Man

12

รหัสของคุณกำลังอ่านลำดับของไบต์ที่เข้ารหัส UTF8 และถอดรหัสโดยใช้การเข้ารหัส 8 บิต

คุณต้องแก้ไขรหัสนั้นเพื่อถอดรหัสไบต์เป็น UTF8

อีกทางเลือกหนึ่ง ( ไม่เหมาะ ) คุณสามารถแปลงสตริงที่ไม่ดีกลับไปเป็นอาร์เรย์ไบต์ดั้งเดิมได้โดยการเข้ารหัสโดยใช้การเข้ารหัสที่ไม่ถูกต้องจากนั้นถอดรหัสไบต์ใหม่เป็น UTF8


ขอบคุณ! ปัญหาคือแอพของบุคคลที่สามคือ C ++ ในขณะที่รหัสของฉันคือ C # ดังนั้นฉันจึงเดาว่าการถอดรหัสเกิดขึ้นใน "สะพาน" ระหว่างทั้งสอง
กาอาระ


5

หากคุณต้องการบันทึกสตริงใด ๆ ลงในฐานข้อมูล mysql ให้ทำดังนี้: ->

โครงสร้างฟิลด์ฐานข้อมูลของคุณฉัน phpmyadmin [หรือแผงควบคุมอื่น ๆ ] ควรตั้งค่าเป็น utf8-gerneral-ci

2) คุณควรเปลี่ยนสตริงของคุณ textbox1.text] ถึงไบต์ดังนั้น

2-1) กำหนดไบต์ [] st2;

2-2) แปลงสตริงของคุณ [textbox1.text] เป็น unicode [mmultibyte string] โดย:

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 แทนการเพิ่มในพารามิเตอร์คำสั่งเช่นด้านล่าง:

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();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.