C # dilinde dizeyi UTF-8'e nasıl dönüştürebilirim?


154

Üçüncü taraf bir uygulamadan aldığım bir dizem var ve Windows Yüzeyimde C # kullanarak herhangi bir dilde doğru şekilde görüntülemek istiyorum.

Hatalı kodlama nedeniyle dizemin bir parçası İspanyolcada şöyle görünüyor:

Acción

oysa şöyle görünmelidir:

Acción

Bu sorunun cevabına göre: C # 'da string kodlaması nasıl anlaşılır, aldığım kodlama UTF-8 üzerinde zaten geliyor olmalı, ancak Encoding.Default üzerinde okunuyor (muhtemelen ANSI?).

Bu dizeyi gerçek UTF-8'e dönüştürmeye çalışıyorum, ancak sorunlardan biri, Kodlama sınıfının yalnızca bir alt kümesini görebiliyor olmam (yalnızca UTF8 ve Unicode özellikleri), çünkü muhtemelen Windows yüzey API'siyle sınırlı olmam.

İnternette bulduğum bazı parçacıkları denedim, ancak şimdiye kadar hiçbiri doğu dilleri (yani Korece) için başarılı olamadı. Bir örnek aşağıdaki gibidir:

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

Ayrıca dizeyi bir bayt dizisine çıkarmayı ve ardından UTF8.GetString'i kullanmayı denedim:

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

Deneyebileceğim başka fikirleriniz var mı?


5
Sizin sorununuz dizeyi oluşturan koddan (bir akıştan veya bayt [] 'dan) ilk etapta geliyor. Lütfen bu kodu gösterin.
SLaks

1
@ Kodlandı: .Net dizeleri bellekte UTF16 olarak saklanır, ancak Encoding.Defaultsistemin ANSI kod sayfasını döndürür.
SLaks

İşte İngilizce dilinde çalışmayan bir dize örneği: Günleri görüntülemek yerine, ön uç uygulamam şunu gösteriyor: dayâ € ™ s
Gaara

Yanıtlar:


262

Bildiğiniz gibi Encoding.Default, basitçe kullanabileceğiniz gibi dize geliyor :

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

Hatırlamanız gerekebilecek başka bir şey: Bazı dizelerin çıktısını almak için Console.WriteLine kullanıyorsanız, o zaman da yazmalısınız Console.OutputEncoding = System.Text.Encoding.UTF8;!!! Veya tüm utf8 dizeleri gbk olarak çıktılanacaktır ...


Bu da işe yarıyor aslında
cevabımdan

Teşekkürler! Sorun şu ki, açıklamada da bahsettiğim gibi, yüzey için API eksiktir (Encoding.Default benim için mevcut değil).
Gaara

3
@Gaara: Deneyin Encoding.GetEncoding(...); diğer uçta yanlış kullanılan gerçek kodlamanın adını bulmanız gerekecektir.
SLaks

1
bunun neden işe yaradığını açıklayabilir misin? Varsayılan GB2312 ise, Encoding.Default.GetBytes dizeyi bayt dizisine kodlayacaktır ve GB2312 kodlayıcısını kullanacaktır, ardından Encoding.UTF8.GetString UTF8 kod çözücüsünü kullanan bayt dizisinin kodunu çözmeye çalışacaktır, sonuç yanlış olmalıdır, ancak bu neden işe yarar. @anothershrubery
guorongfei

1
@guorongfei Öncül myString, mojibake olmasıdır. Kod önce yanlış kod çözmeyi geri alır, ardından doğru kod çözmeyi yapar. Yanlış kod çözme veri kaybetmediği sürece çalışır. Ancak @SLaks'ın da belirttiği gibi, yanlış olan tam kodlamayı kullanmak daha iyi olurdu. (Koddaki daha iyi isimler ve yorumlar, çok yanlış görünen kodun aslında doğru yapma girişimi olduğunun anlaşılmasına yardımcı olacaktır.)
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);

Çıktı şöyle görünmeli

Acción

gün, günü gösterir

DecodeFromUtf8 () çağırın;

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

1
Teşekkürler! İspanyolca çalışıyor, sorun aynı şeyin doğu dillerinde (yani Korece) çalışmaması. İnternette 8-bit'ten UTF-8'e dönüştürme algoritması aramaya çalışıyorum ama yine de şansım yok.
Gaara

İşte İngilizce dilinde çalışmayan bir dize örneği: Günleri görüntülemek yerine, ön uç uygulamam şunu gösteriyor: dayâ € ™ s
Gaara

tamam, bununla
uğraşmama

Test ettim ve gün döndürüyor Test ettiğim statik yöntemi yapıştıracağım, aslında @anothershrubery'nin sağladığı ile aynı
MethodMan

DecodeFromUtf8 (string utf8string) ileterek bu yöntemi değiştirebilirsiniz;
MethodMan

12

Kodunuz, UTF8 kodlu bir bayt dizisini okuyor ve 8 bit kodlama kullanarak bunların kodunu çözüyor.

Baytları UTF8 olarak çözmek için bu kodu düzeltmeniz gerekir.

Alternatif olarak ( ideal değil ), hatalı dizgiyi - yanlış kodlamayı kullanarak kodlayarak - orijinal bayt dizisine geri dönüştürebilir ve ardından baytları UTF8 olarak yeniden çözebilirsiniz.


Teşekkürler! Sorun şu ki, kodum C # iken üçüncü taraf uygulaması C ++, bu yüzden kod çözme bu ikisi arasındaki "köprü" de oluyor.
Gaara

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

5

Herhangi bir dizeyi mysql veritabanına kaydetmek istiyorsanız şunu yapın: ->

Veritabanı alan yapınız phpmyadmin [veya başka bir kontrol paneli] utf8-gerneral-ci olarak ayarlanmalıdır

2) [Örn. textbox1.text] 'i byte'a, bunun için

2-1) bayt [] st2'yi tanımlayın;

2-2) [textbox1.text] dizenizi unicode [mmultibyte string] 'e şu şekilde dönüştürün:

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

3) herhangi bir sorgudan önce bu sql komutunu çalıştırın:

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

3-2) şimdi bu değeri örneğin ad alanına şu şekilde eklemelisiniz:

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

4) birçok çözümün dikkat etmediği ana iş aşağıdaki satırdır: aşağıdaki gibi komut parametresini eklemek yerine addwithvalue kullanmalısınız:

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

+++++++++++++++++++++++++++++++++ Veritabanı sunucunuzdaki gerçek verilerin tadını çıkarın ????


3

Csv dosyasından bayt almak için aşağıdaki kod parçacığını kullanın

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;
    }

Aşağıdakileri arayın ve ek olarak kaydedin

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

3

@anothershrubery cevabı benim için çalıştı. StringEntensions Class'ı kullanarak programımdaki herhangi bir dizeyi kolayca dönüştürebilmek için bir geliştirme yaptım .

Yöntem:

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

Kullanım:

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

Ya da sadece:

string strConverted = "Acción".ToUTF8();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.