Come rilevare automaticamente la codifica dei file di testo?


69

Esistono molti file di testo semplice codificati in set di caratteri varianti.

Voglio convertirli tutti in UTF-8, ma prima di eseguire iconv, devo conoscere la sua codifica originale. La maggior parte dei browser ha Auto Detectun'opzione nelle codifiche, tuttavia, non posso controllare quei file di testo uno per uno perché ce ne sono troppi.

Solo dopo aver conosciuto la codifica originale, posso quindi convertire i testi di iconv -f DETECTED_CHARSET -t utf-8.

Esiste qualche utilità per rilevare la codifica di file di testo normale? NON deve essere perfetto al 100%, non mi dispiace se ci sono 100 file erroneamente convertiti in 1.000.000 di file.

Risposte:


57

Prova il modulo chardet Python, disponibile su PyPi:

pip install chardet

Quindi corri chardetect myfile.txt.

Chardet si basa sul codice di rilevamento utilizzato da Mozilla, quindi dovrebbe fornire risultati ragionevoli, a condizione che il testo di input sia sufficientemente lungo per l'analisi statistica. Leggi la documentazione del progetto .

Come accennato nei commenti, è piuttosto lento, ma alcune distribuzioni distribuiscono anche la versione C ++ originale come @Xavier ha trovato in https://superuser.com/a/609056 . C'è anche una versione Java da qualche parte.


3
Sì, ed è già impacchettato come python-chardetnel repository universo Ubuntu.
Xiè Jìléi,

Se non fosse un'ipotesi perfetta, chardetdarebbe comunque l'ipotesi più corretta, come ./a.txt: GB2312 (confidence: 0.99). Rispetto a Enca che ha appena fallito e riporta "Codifica non riconosciuta". Tuttavia, purtroppo, chardetfunziona molto lentamente.
Xiè Jìléi,

1
@ 谢 继 雷: fallo correre durante la notte o qualcosa del genere. Il rilevamento dei set di caratteri è un processo complicato . Potresti anche provare jChardet basato su Java o ... il chardet originale fa parte di Mozilla , ma è disponibile solo il sorgente C ++, nessuno strumento da riga di comando.
Grawity

2
Per quanto riguarda la velocità: la corsa è chardet <(head -c4000 filename.txt)stata molto più veloce e ugualmente riuscita per il mio caso d'uso. (nel caso in cui non sia chiaro che questa sintassi bash invierà solo i primi 4000 byte a chardet)
ndemou,

@ndemou chardet==3.0.4, e il vero nome eseguibile dello strumento da riga di comando chardetectnon lo è chardet.
Devy,

32

Vorrei usare questo semplice comando:

encoding=$(file -bi myfile.txt)

O se vuoi solo il set di caratteri reale (come utf-8):

encoding=$(file -b --mime-encoding myfile.txt)

4
Sfortunatamente, filerileva solo codifiche con proprietà specifiche, come UTF-8 o UTF-16. Il resto - il vecchio ISO8859 o i corrispondenti MS-DOS e Windows - sono elencati come "unknown-8bit" o qualcosa di simile, anche per i file che chardetrilevano con una sicurezza del 99%.
Grawity,

6
il file mi mostrava iso-8859-1
cweiske il

E se l'estensione sta mentendo?
james.garriss,

2
@ james.garriss: l'estensione del file non ha nulla a che fare con la sua codifica del contenuto (di testo).
MestreLion,

29

Su Linux basato su Debian, il pacchetto uchardet ( Debian / Ubuntu ) fornisce uno strumento da riga di comando. Vedi sotto la descrizione del pacchetto:

 universal charset detection library - cli utility
 .
 uchardet is a C language binding of the original C++ implementation
 of the universal charset detection library by Mozilla.
 .
 uchardet is a encoding detector library, which takes a sequence of
 bytes in an unknown character encoding without any additional
 information, and attempts to determine the encoding of the text.
 .
 The original code of universalchardet is available at
 http://lxr.mozilla.org/seamonkey/source/extensions/universalchardet
 .
 Techniques used by universalchardet are described at
 http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html

3
Grazie! Dalla homepage del progetto non era ovvio per me che fosse inclusa una CLI. È disponibile anche su OS X durante l'installazione uchardettramite Homebrew.
Stefan Schmidt,

1
All'inizio ero un po 'confuso perché un documento ISO 8859-1 è stato erroneamente identificato come Windows-1252 ma nell'intervallo stampabile Windows-1252 è un superset di ISO 8859-1, quindi la conversione con iconvfunziona correttamente.
Stefan Schmidt,

16

Per Linux esiste enca e per Solaris è possibile utilizzare auto_ef .


Enca mi sembra troppo severo: enca -d -L zh ./a.txtfallito con il messaggio ./a.txt: Unrecognized encoding Failure reason: No clear winner.Come accennato da @grawity, chardetè più rilassato, tuttavia è ancora troppo lento.
Xiè Jìléi,

10
Enca fallisce completamente il test "effettivamente fa qualcosa".
Michael Wolf,

1
uchardet fallito (rilevato CP1252 anziché l'attuale CP1250), ma enca ha funzionato bene. (esempio unico, difficile da generalizzare ...)
Palo


2

Tornando a chardet (python 2.?) Questa chiamata potrebbe essere sufficiente:

python -c 'import chardet,sys; print chardet.detect(sys.stdin.read())' < file
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'}

Anche se è tutt'altro che perfetto ...

echo "öasd" | iconv -t ISO-8859-1 | python -c 'import chardet,sys; print chardet.detect(sys.stdin.read())'
{'confidence': 0.5, 'encoding': 'windows-1252'}

2

Per coloro che utilizzano regolarmente Emacs, potrebbero trovare utili le seguenti informazioni (consente di ispezionare e validare manualmente la trasfomazione).

Inoltre, trovo spesso che il rilevamento automatico del set di caratteri Emacs sia molto più efficiente rispetto agli altri strumenti di rilevamento automatico del set di caratteri (come chardet).

(setq paths (mapcar 'file-truename '(
 "path/to/file1"
 "path/to/file2"
 "path/to/file3"
)))

(dolist (path paths)
  (find-file path)
  (set-buffer-file-coding-system 'utf-8-unix)
  )

Quindi, una semplice chiamata a Emacs con questo script come argomento (vedere l'opzione "-l") fa il lavoro.



0

isutf8(dal moreutilspacchetto) ha fatto il lavoro


2
Come? Questa risposta non è davvero utile.
Mosè,

1
Non è stato chiesto esattamente, ma è uno strumento utile. Se il file è UTF-8 valido, lo stato di uscita è zero. Se il file non è valido UTF-8 o si verifica un errore, lo stato di uscita è diverso da zero.
ton

0

Anche nel caso in cui il file -i ti dia sconosciuto

Puoi usare questo comando php che può indovinare charset come di seguito:

In php puoi controllare come di seguito:

Specificare esplicitamente l'elenco di codifica:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

" Mb_list_encodings " più accurati :

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"

Qui nel primo esempio, puoi vedere che ho messo un elenco di codifiche (rileva l'ordine dell'elenco) che potrebbero corrispondere. Per ottenere risultati più precisi è possibile utilizzare tutte le codifiche possibili tramite: mb_list_encodings ()

Nota le funzioni mb_ * richiedono php-mbstring

apt-get install php-mbstring 

Vedi risposta: https://stackoverflow.com/a/57010566/3382822

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.