2009-09-19 6 views
6

Ho un'enorme tabella MySQL che ha le sue righe codificate in UTF-8 due volte. Ad esempio "Újratárgyalja" è memorizzato come "Újratárgyalja".Come decodificare una stringa che è stata codificata in UTF-8 due volte in UTF-8 semplice?

Il connettore MySQL .Net li scarica in questo modo. Ho provato molte combinazioni con System.Text.Encoding.Convert() ma nessuno di loro ha funzionato.

L'invio di set names 'utf8' (o altro set di caratteri) non lo risolverà.

Come posso decodificarli da doppio UTF-8 a UTF-8?

+1

devo upvote questa domanda, soprattutto perché ha spinto la risposta di Alex, che è dannatamente ingegnoso. Inoltre, la codifica può essere un affare complicato in generale, poiché ho riscoperto solo sperimentando la risposta di Alex sulla mia macchina. Ho la sensazione che il suo approccio possa aiutare (almeno come indizio) anche in altri contesti di interoperabilità. –

risposta

8

Problema particolare, ma penso di poterlo riprodurre con un miscuglio appropriato di UTF-8 e Latin-1 (non con solo due usi di UTF-8 senza un mis-step intervallato in Latin-1) . Ecco tutto il viaggio di andata strano "andata e ritorno di nuovo" (Python 2. * o IronPython dovrebbe sia essere in grado di riprodurre questo):

# -*- coding: utf-8 -*- 
uni = u'Újratárgyalja' 
enc1 = uni.encode('utf-8') 
enc2 = enc1.decode('latin-1').encode('utf-8') 
dec3 = enc2.decode('utf-8') 
dec4 = dec3.encode('latin-1').decode('utf-8') 

for x in (uni, enc1, enc2, dec3, dec4): 
    print repr(x), x 

Questa è l'uscita interessante ...:

u'\xdajrat\xe1rgyalja' Újratárgyalja 
'\xc3\x9ajrat\xc3\xa1rgyalja' Újratárgyalja 
'\xc3\x83\xc2\x9ajrat\xc3\x83\xc2\xa1rgyalja' Ãjratárgyalja 
u'\xc3\x9ajrat\xc3\xa1rgyalja' Ãjratárgyalja 
u'\xdajrat\xe1rgyalja' Újratárgyalja 

La stringa strana che inizia con à appare come enc2, cioè due codifiche utf-8 con una decodifica latin-1 intervallata gettata nel mix. E come puoi vedere, può essere annullato dalla sequenza di operazioni esattamente inverse: decodifica come utf-8, ri-codifica come latin-1, ri-decodifica come utf-8 di nuovo - e la stringa originale è tornata (yay !).

Credo che le normali proprietà di round-trip sia di Latin-1 (ovvero ISO-8859-1) sia di UTF-8 dovrebbero garantire che questa sequenza funzioni (scusa, nessun C# intorno a provare in quella lingua in questo momento , ma mi aspetto che le sequenze di codifica/decodifica non dipendano dallo specifico linguaggio di programmazione in uso).

+0

Geniale. E la risposta è accettata. Per mia curiosità, però, ho provato a riprodurre i risultati su Windows con Python 2.6.1. È stato un periodo difficile, perché l'atto stesso di copiare e incollare il codice ha creato problemi (ad esempio, incollare nel Blocco note e l'editor IDLE erano molto diversi!).Quindi l'esecuzione ha creato più problemi (ha dovuto ricorrere alla stampa solo repr (x) se al di fuori di IDLE). [Lo so, lo so, ottenere un vero sistema operativo, ecc.] –

-1

Si potrebbe provare a utilizzare

SELECT CONVERT(`your_column` USING ascii) 
FROM `your_table` 

a livello di query MySQL. Questa è una pugnalata al buio, però.

1

Quando si scrive "Il connettore MySQL .Net li scarica in questo modo". c'è una buona possibilità che questo significhi che il connettore .Net di MySQL crede che stia parlando Latin-1 a MySQL, mentre MySQL crede che la conversazione sia in UTF-8. C'è anche la possibilità che la colonna sia dichiarata come Latin-1, ma in realtà contiene dati UTF-8.

Se è il secondo (colonna con etichetta Latin-1 ma i dati sono in realtà UTF-8) si ottengono misteriosi problemi di collazione e altri bug se si utilizzano le funzioni di elaborazione del testo di MySQL, ORDER BY sulla colonna o altre situazioni dove il testo "significa qualcosa" piuttosto che essere semplicemente i byte inviati sul filo.

In entrambi i casi si dovrebbe provare a risolvere il problema sottostante, non ultimo perché sarà un mal di testa completo per chiunque debba mantenere il sistema in caso contrario.

+0

La colonna è dichiarata come UTF-8 e anche i dati in essa contenuti sono UTF-8, ma per alcuni misteriosi motivi l'estensione PDO di PHP lo ha codificato due volte. – RoliSoft

+0

Prima non hai mai parlato di PHP. Quindi i dati sono realmente corrotti nel DB MySQL? – tialaramex

+0

L'ho menzionato giusto nella prima frase, che è archiviato nel database MySQL in questo modo. Tuttavia, non ho detto che l'estensione PDO di PHP li ha memorizzati in questo modo, perché la domanda iniziale era come decodificare una stringa in C# codificata in UTF-8 due volte. – RoliSoft