Come posso trasformare la stringa in UTF-8 in C #?


146

Ho una stringa che ricevo da un'app di terze parti e vorrei visualizzarla correttamente in qualsiasi lingua usando C # sul mio Windows Surface.

A causa di una codifica errata, un pezzo della mia stringa appare così in spagnolo:

Acción

mentre dovrebbe apparire così:

acción

Secondo la risposta a questa domanda: Come sapere la codifica di stringa in C # , la codifica che sto ricevendo dovrebbe essere già in UTF-8, ma è letta su Encoding.Default (probabilmente ANSI?).

Sto cercando di trasformare questa stringa in reale UTF-8, ma uno dei problemi è che riesco a vedere solo un sottoinsieme della classe Encoding (solo proprietà UTF8 e Unicode), probabilmente perché sono limitato all'API di Windows Surface.

Ho provato alcuni frammenti che ho trovato su Internet, ma nessuno di questi ha finora avuto successo per le lingue orientali (ad esempio il coreano). Un esempio è il seguente:

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

Ho anche provato a estrarre la stringa in una matrice di byte e quindi usando 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);

Ragazzi avete altre idee che potrei provare?


5
Il tuo problema proviene innanzitutto dal codice che ha creato la stringa (da uno stream o byte []). Si prega di mostrare quel codice.
SLaks,

1
@Oded: le stringhe .Net sono archiviate in memoria come UTF16, ma Encoding.Defaultrestituiscono la tabella codici ANSI del sistema.
SLaks,

Ecco un esempio di una stringa che non funziona sulla lingua inglese: invece di visualizzare day's, viene visualizzata la mia app front-end: dayâ € ™ s
Gaara

Risposte:


251

Come sai la stringa sta arrivando come Encoding.Defaultpotresti semplicemente usare:

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

Un'altra cosa che potresti dover ricordare: se stai utilizzando Console.WriteLine per produrre alcune stringhe, dovresti anche scrivere Console.OutputEncoding = System.Text.Encoding.UTF8;!!! O tutte le stringhe utf8 verranno emesse come gbk ...


Anche questo funziona, in realtà è molto più bello della mia risposta, che funziona anche. Ti sto dando un bel lavoro +1
MethodMan

Grazie! Il problema è che, come ho detto nella descrizione, l'API per Surface è incompleta (nessun Encoding.Default disponibile per me).
Gaara,

3
@Gaara: Try Encoding.GetEncoding(...); dovrai trovare il nome della codifica effettiva che è stata erroneamente utilizzata dall'altra parte.
SLaks,

1
puoi spiegare perché funziona? se il valore predefinito è GB2312, Encoding.Default.GetBytes codificherà la stringa nell'array di byte utilizzando l'encoder GB2312, quindi Encoding.UTF8.GetString proverà a decodificare l'array di byte utilizzando il decoder UTF8, il risultato dovrebbe essere errato, ma perché funziona. @anothershrubery
guorongfei,

1
@guorongfei La premessa è che myStringè mojibake. Il codice annulla prima la decodifica sbagliata, quindi esegue la decodifica corretta. Funziona finché la decodifica sbagliata non ha perso i dati. Ma come ha sottolineato @SLaks, sarebbe meglio usare la codifica esatta che era sbagliata. (Nomi e commenti migliori nel codice aiuterebbero a capire quanto un codice dall'aspetto errato sia in realtà un tentativo di fare bene.)
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);

L'output dovrebbe essere simile

acción

dayâ € ™ s visualizza day's

chiama DecodeFromUtf8 ();

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

1
Grazie! Funziona in spagnolo, il problema è che lo stesso non funzionerebbe con le lingue orientali (coreane). Sto cercando un algoritmo di conversione da 8 bit a UTF-8 su Internet, ma non ho ancora avuto fortuna.
Gaara,

Ecco un esempio di una stringa che non funziona sulla lingua inglese: invece di visualizzare day's, viene visualizzata la mia app front-end: dayâ € ™ s
Gaara

ok fammi fare un giro con esso e vedere cosa riesco a trovare
MethodMan,

Ho provato e ritorna il giorno in cui incollerò il metodo statico che ho testato è in realtà lo stesso di quello che ha fornito
@anothershrubery

puoi modificare quel metodo passando DecodeFromUtf8 (stringa utf8string);
MethodMan,

12

Il codice legge una sequenza di byte codificati UTF8 e li decodifica utilizzando una codifica a 8 bit.

È necessario correggere quel codice per decodificare i byte come UTF8.

In alternativa ( non ideale ), è possibile riconvertire la stringa errata nell'array di byte originale — codificandola utilizzando una codifica errata — quindi ricodificare i byte come UTF8.


Grazie! Il problema è che l'app di terze parti è C ++, mentre il mio codice è C #, quindi immagino che la decodifica avvenga nel "ponte" tra quei due.
Gaara,

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

5

Se si desidera salvare una stringa nel database mysql, procedere come segue: ->

La struttura del campo del database i phpmyadmin [o qualsiasi altro pannello di controllo] dovrebbe essere impostata su utf8-gerneral-ci

2) dovresti cambiare la tua stringa [Es. textbox1.text] in byte, quindi

2-1) definisci byte [] st2;

2-2) converti la tua stringa [textbox1.text] in unicode [mmultibyte string] di:

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

3) eseguire questo comando sql prima di qualsiasi query:

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

3-2) ora è necessario inserire questo valore nel campo nome, ad esempio:

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

4) il lavoro principale a cui molte soluzioni non hanno prestato attenzione è la riga sottostante: dovresti usare addwithvalue invece di aggiungere il parametro di comando come di seguito:

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

++++++++++++++++++++++++++++++++++++ godono di dati reali nel tuo server di database anziché ????


3

Utilizzare lo snippet di codice seguente per ottenere byte dal 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;
    }

Chiama il seguito e salvalo come allegato

           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();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.