Bagaimana saya bisa mengubah string menjadi UTF-8 di C #?

146

Saya memiliki string yang saya terima dari aplikasi pihak ketiga dan saya ingin menampilkannya dengan benar dalam bahasa apa pun menggunakan C # di Windows Surface saya.

Karena penyandian yang salah, seutas string saya terlihat seperti ini dalam bahasa Spanyol:

Acción

padahal seharusnya terlihat seperti ini:

Acción

Menurut jawaban pada pertanyaan ini: Bagaimana cara mengetahui pengkodean string dalam C # , pengkodean yang saya terima seharusnya sudah datang pada UTF-8, tetapi dibaca pada Pengkodean. Kerusakan (mungkin ANSI?).

Saya mencoba untuk mengubah string ini menjadi UTF-8 nyata, tetapi salah satu masalah adalah bahwa saya hanya bisa melihat subset dari kelas Encoding (properti UTF8 dan Unicode saja), mungkin karena saya terbatas pada permukaan jendela API.

Saya telah mencoba beberapa cuplikan yang saya temukan di internet, tetapi sejauh ini belum ada yang terbukti berhasil untuk bahasa timur (yaitu bahasa Korea). Salah satu contohnya adalah sebagai berikut:

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

Saya juga mencoba mengekstraksi string ke array byte dan kemudian menggunakan 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);

Apakah kalian punya ide lain yang bisa saya coba?

Gaara
sumber
5
Masalah Anda berasal dari kode yang menciptakan string (dari aliran atau byte []) di tempat pertama. Tolong tunjukkan kode itu.
SLaks
1
@Oded: .Net string disimpan dalam memori sebagai UTF16, tetapi Encoding.Defaultmengembalikan kode situs ANSI.
SLaks
Berikut adalah contoh string yang tidak berfungsi pada bahasa Inggris: alih-alih menampilkan hari, aplikasi ujung depan saya menampilkan: dayâ € ™ s
Gaara

Jawaban:

251

Seperti yang Anda ketahui, string masuk karena Encoding.DefaultAnda bisa menggunakan:

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

Hal lain yang mungkin harus Anda ingat: Jika Anda menggunakan Console.WriteLine untuk menampilkan beberapa string, maka Anda juga harus menulis Console.OutputEncoding = System.Text.Encoding.UTF8;!!! Atau semua string utf8 akan di-output sebagai gbk ...

anothershrubery
sumber
Ini berfungsi juga sebenarnya jauh lebih bagus daripada jawaban saya yang juga berfungsi saya memberi Anda karya bagus +1
MethodMan
Terima kasih! Masalahnya adalah bahwa, seperti yang saya sebutkan dalam deskripsi, API untuk permukaan tidak lengkap (tidak ada Encoding.Default tersedia untuk saya).
Gaara
3
@ Gaara: Coba Encoding.GetEncoding(...); Anda harus menemukan nama penyandian aktual yang salah digunakan di ujung lainnya.
SLaks
1
dapatkah Anda menjelaskan mengapa ini berhasil? jika Default adalah GB2312, maka Encoding.Default.GetBytes akan menyandikan string ke byte array menggunakan GB2312 encoder, kemudian Encoding.UTF8.GetString akan mencoba untuk mendekode array byte menggunakan UTF8 decoder, hasilnya harus salah, tetapi mengapa ini bekerja. @anothershrubery
guorongfei
1
@guorongfei Premisnya myStringadalah mojibake. Pertama-tama kode membatalkan decoding yang salah kemudian melakukan decoding yang benar. Ini berfungsi selama decoding yang salah tidak kehilangan data. Tetapi seperti yang ditunjukkan oleh @SLaks, akan lebih baik untuk menggunakan penyandian yang salah. (Nama dan komentar yang lebih baik dalam kode akan membantu memahami bagaimana kode yang kelihatannya salah sebenarnya merupakan upaya melakukan yang benar.)
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);

Output akan terlihat seperti

Acción

day's day's day's

panggil DecodeFromUtf8 ();

private static void DecodeFromUtf8()
{
    string utf8_String = "day’s";
    byte[] bytes = Encoding.Default.GetBytes(utf8_String);
    utf8_String = Encoding.UTF8.GetString(bytes);
}
MethodMan
sumber
1
Terima kasih! Ini berfungsi dalam bahasa Spanyol, masalahnya adalah hal yang sama tidak berlaku pada bahasa-bahasa timur (yaitu bahasa Korea). Saya mencoba mencari algoritma konversi 8-bit ke UTF-8 di internet, tetapi masih belum berhasil.
Gaara
Berikut adalah contoh string yang tidak berfungsi pada bahasa Inggris: alih-alih menampilkan hari, aplikasi ujung depan saya menampilkan: dayâ € ™ s
Gaara
ok biarkan aku mengacaukannya dan lihat apa yang bisa
kukerjakan
Saya menguji dan mengembalikan hari saya akan menempelkan metode statis yang saya uji itu sebenarnya sama dengan apa yang telah diberikan
@anothershrubery
Anda dapat mengubah metode itu dengan mengirimkan DecodeFromUtf8 (string utf8string);
MethodMan
12

Kode Anda membaca urutan byte yang dikodekan oleh UTF8, dan mendekodekannya menggunakan pengkodean 8-bit.

Anda perlu memperbaiki kode itu untuk mendekode byte sebagai UTF8.

Atau ( tidak ideal ), Anda dapat mengonversi string buruk kembali ke array byte asli — dengan mengkodekannya menggunakan pengkodean yang salah — kemudian mendekode ulang byte sebagai UTF8.

Slaks
sumber
Terima kasih! Masalahnya adalah bahwa aplikasi pihak ketiga adalah C ++, sedangkan kode saya adalah C #, jadi saya kira decoding terjadi di "jembatan" antara keduanya.
Gaara
8
 Encoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(mystring));
Riadh Hammouda
sumber
5

Jika Anda ingin menyimpan string ke database mysql, lakukan ini: ->

Struktur bidang basis data Anda di phpmyadmin [atau panel kontrol lain] harus disetel ke utf8-gerneral-ci

2) Anda harus mengubah string Anda [Kel. textbox1.text] ke byte, karenanya

2-1) define byte [] st2;

2-2) konversi string Anda [textbox1.text] menjadi unicode [mmultibyte string] oleh:

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

3) jalankan perintah sql ini sebelum permintaan:

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

3-2) sekarang Anda harus memasukkan nilai ini ke misalnya bidang nama dengan:

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

4) pekerjaan utama yang tidak diperhatikan oleh banyak solusi adalah baris di bawah ini: Anda harus menggunakan addwithvalue alih-alih menambahkan parameter perintah seperti di bawah ini:

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

+++++++++++++++++++++++++++++++++ menikmati data nyata di server database Anda, bukan ????

Hassan Fadaie Ghotbie
sumber
3

Gunakan cuplikan kode di bawah ini untuk mendapatkan byte dari file 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;
    }

Panggil di bawah ini dan simpan sebagai lampiran

           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();
jtoni
sumber