Wie kann ich einen String in C # in UTF-8 umwandeln?

146

Ich habe eine Zeichenfolge, die ich von einer Drittanbieter-App erhalte, und möchte sie in jeder Sprache mit C # auf meiner Windows-Oberfläche korrekt anzeigen.

Aufgrund der falschen Codierung sieht ein Teil meiner Zeichenfolge auf Spanisch folgendermaßen aus:

Acción

während es so aussehen sollte:

Acción

Gemäß der Antwort auf diese Frage: Wie man die Zeichenfolgencodierung in C # kennt , sollte die Codierung, die ich erhalte, bereits auf UTF-8 verfügbar sein, sie wird jedoch auf Encoding.Default (wahrscheinlich ANSI?) Gelesen.

Ich versuche, diese Zeichenfolge in echtes UTF-8 umzuwandeln, aber eines der Probleme besteht darin, dass ich nur eine Teilmenge der Encoding-Klasse sehen kann (nur UTF8- und Unicode-Eigenschaften), wahrscheinlich weil ich auf die Windows-Oberflächen-API beschränkt bin.

Ich habe einige Schnipsel ausprobiert, die ich im Internet gefunden habe, aber keines davon hat sich bisher für östliche Sprachen (dh Koreanisch) als erfolgreich erwiesen. Ein Beispiel ist wie folgt:

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

Ich habe auch versucht, die Zeichenfolge in ein Byte-Array zu extrahieren und dann UTF8.GetString zu verwenden:

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

Habt ihr noch andere Ideen, die ich ausprobieren könnte?

Gaara
quelle
5
Ihr Problem kommt von dem Code, der die Zeichenfolge (aus einem Stream oder Byte []) erstellt hat. Bitte zeigen Sie diesen Code.
SLaks
1
@Oded: .Net-Zeichenfolgen werden als UTF16 im Speicher gespeichert, geben jedoch Encoding.Defaultdie ANSI-Codepage des Systems zurück.
SLaks
Hier ist ein Beispiel für eine Zeichenfolge, die in der englischen Sprache nicht funktioniert: Anstatt den Tag anzuzeigen, zeigt meine Front-End-App Folgendes an: Tag
Gaara

Antworten:

251

Wie Sie wissen, kommt die Zeichenfolge herein, da Encoding.DefaultSie einfach Folgendes verwenden könnten:

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

Eine andere Sache, die Sie möglicherweise beachten müssen: Wenn Sie Console.WriteLine verwenden, um einige Zeichenfolgen auszugeben, sollten Sie auch schreiben Console.OutputEncoding = System.Text.Encoding.UTF8;!!! Oder alle utf8-Strings werden als gbk ausgegeben ...

Anothershrubery
quelle
Dies funktioniert auch, es ist tatsächlich viel schöner als meine Antwort, die auch funktioniert. Ich gebe Ihnen eine +1 schöne Arbeit
MethodMan
Vielen Dank! Das Problem ist, dass, wie in der Beschreibung erwähnt, die API für die Oberfläche unvollständig ist (für mich ist kein Encoding.Default verfügbar).
Gaara
3
@ Gaara: Versuchen Sie es Encoding.GetEncoding(...); Sie müssen den Namen der tatsächlichen Codierung finden, die am anderen Ende falsch verwendet wurde.
SLaks
1
Kannst du erklären, warum das funktioniert? Wenn der Standardwert GB2312 ist, codiert Encoding.Default.GetBytes die Zeichenfolge in ein Byte-Array mit dem GB2312-Encoder. Dann versucht Encoding.UTF8.GetString, das Byte-Array mithilfe des UTF8-Decoders zu decodieren. Das Ergebnis sollte falsch sein, aber warum funktioniert dies? @anothershrubery
guorongfei
1
@guorongfei Die Prämisse ist, dass myStringMojibake ist. Der Code macht zuerst die falsche Dekodierung rückgängig und führt dann die richtige Dekodierung durch. Es funktioniert, solange die falsche Dekodierung keine Daten verloren hat. Aber wie @SLaks betonte, wäre es besser, die genaue Codierung zu verwenden, die falsch war. (Bessere Namen und Kommentare im Code würden helfen zu verstehen, wie sehr falsch aussehender Code tatsächlich ein Versuch ist, richtig zu machen.)
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);

Die Ausgabe sollte so aussehen

Acción

Tagesanzeigen Tag

call DecodeFromUtf8 ();

private static void DecodeFromUtf8()
{
    string utf8_String = "day’s";
    byte[] bytes = Encoding.Default.GetBytes(utf8_String);
    utf8_String = Encoding.UTF8.GetString(bytes);
}
Method Man
quelle
1
Vielen Dank! Es funktioniert auf Spanisch, das Problem ist, dass das Gleiche nicht für östliche Sprachen (dh Koreanisch) funktioniert. Ich versuche im Internet nach einem 8-Bit-zu-UTF-8-Konvertierungsalgorithmus zu suchen, habe aber immer noch kein Glück.
Gaara
Hier ist ein Beispiel für eine Zeichenfolge, die in der englischen Sprache nicht funktioniert: Anstatt den Tag anzuzeigen, zeigt meine Front-End-App Folgendes an: Tag
Gaara
ok lass mich damit
herumspielen
Ich habe getestet und es gibt den Tag zurück. Ich werde die statische Methode einfügen, die ich getestet habe. Sie ist tatsächlich die gleiche wie die, die @anothershrubery bereitgestellt hat
MethodMan
Sie können diese Methode ändern, indem Sie DecodeFromUtf8 (string utf8string) übergeben.
MethodMan
12

Ihr Code liest eine Folge von UTF8-codierten Bytes und decodiert sie mithilfe einer 8-Bit-Codierung.

Sie müssen diesen Code korrigieren, um die Bytes als UTF8 zu dekodieren.

Alternativ ( nicht ideal ) können Sie die fehlerhafte Zeichenfolge zurück in das ursprüngliche Byte-Array konvertieren, indem Sie sie mit der falschen Codierung codieren, und dann die Bytes als UTF8 neu decodieren.

SLaks
quelle
Vielen Dank! Das Problem ist, dass die Drittanbieter-App C ++ ist, während mein Code C # ist. Ich denke, die Dekodierung erfolgt in der "Brücke" zwischen diesen beiden.
Gaara
8
 Encoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(mystring));
Riadh Hammouda
quelle
5

Wenn Sie eine Zeichenfolge in der MySQL-Datenbank speichern möchten, gehen Sie wie folgt vor: ->

Ihre Datenbankfeldstruktur i phpmyadmin [oder ein anderes Kontrollfeld] sollte auf utf8-gerneral-ci eingestellt sein

2) Sie sollten Ihre Zeichenfolge ändern [Bsp. textbox1.text] zu Byte, dafür

2-1) definiere Byte [] st2;

2-2) Konvertieren Sie Ihre Zeichenfolge [textbox1.text] in Unicode [mmultibyte string] durch:

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

3) Führen Sie diesen SQL-Befehl vor jeder Abfrage aus:

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

3-2) Jetzt sollten Sie diesen Wert in das Namensfeld einfügen, indem Sie:

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

4) Die Hauptaufgabe, auf die viele Lösungen nicht geachtet haben, ist die folgende Zeile: Sie sollten addwithvalue verwenden, anstatt den folgenden Befehlsparameter hinzuzufügen:

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

++++++++++++++++++++++++++++++++++++ Genießen Sie echte Daten auf Ihrem Datenbankserver anstatt ????

Hassan Fadaie Ghotbie
quelle
3

Verwenden Sie das folgende Code-Snippet, um Bytes aus der CSV-Datei abzurufen

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

Rufen Sie unten an und speichern Sie es als Anhang

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