it-swarm.it

Come posso testare la codifica di un file di testo ... È valido e che cos'è?

Ho diversi .htm file che si aprono in Gedit senza alcun avviso/errore, ma quando apro questi stessi file in Jedit, mi avvisa della codifica UTF-8 non valida ...

Il meta tag HTML indica "charset = ISO-8859-1". Jedit consente un Elenco delle codifiche di fallback e un Elenco dei rilevatori automatici di codifica (attualmente "BOM XML-PI"), quindi il mio problema immediato è stato risolto. Ma questo mi ha fatto pensare: e se i metadati non esistessero?

Quando le informazioni di codifica non sono disponibili, esiste un programma CLI che può fare una "ipotesi" su quali codifiche possono essere applicate?

E, sebbene sia un problema leggermente diverso; esiste un programma CLI che verifica la validità di una codifica nota ?

55
Peter.O

Il comando file fa "ipotesi" sulla codifica. Usa il -i parametro per forzare file per stampare informazioni sulla codifica.

Dimostrazione:

$ file -i *
umlaut-iso88591.txt: text/plain; charset=iso-8859-1
umlaut-utf16.txt:    text/plain; charset=utf-16le
umlaut-utf8.txt:     text/plain; charset=utf-8

Ecco come ho creato i file:

$ echo ä > umlaut-utf8.txt 

Oggi tutto è utf-8. Ma convinciti:

$ hexdump -C umlaut-utf8.txt 
00000000  c3 a4 0a                                          |...|
00000003

Confronta con https://en.wikipedia.org/wiki/Ä#Computer_encoding

Converti in altre codifiche:

$ iconv -f utf8 -t iso88591 umlaut-utf8.txt > umlaut-iso88591.txt 
$ iconv -f utf8 -t utf16 umlaut-utf8.txt > umlaut-utf16.txt 

Controlla la discarica esadecimale:

$ hexdump -C umlaut-iso88591.txt 
00000000  e4 0a                                             |..|
00000002
$ hexdump -C umlaut-utf16.txt 
00000000  ff fe e4 00 0a 00                                 |......|
00000006

Crea qualcosa di "non valido" mescolando tutti e tre:

$ cat umlaut-iso88591.txt umlaut-utf8.txt umlaut-utf16.txt > umlaut-mixed.txt 

Cosa dice file:

$ file -i *
umlaut-iso88591.txt: text/plain; charset=iso-8859-1
umlaut-mixed.txt:    application/octet-stream; charset=binary
umlaut-utf16.txt:    text/plain; charset=utf-16le
umlaut-utf8.txt:     text/plain; charset=utf-8

senza -i:

$ file *
umlaut-iso88591.txt: ISO-8859 text
umlaut-mixed.txt:    data
umlaut-utf16.txt:    Little-endian UTF-16 Unicode text, with no line terminators
umlaut-utf8.txt:     UTF-8 Unicode text

Il comando file non ha idea di "valido" o "non valido". Vede solo alcuni byte e prova a indovinare quale potrebbe essere la codifica. Come umani potremmo essere in grado di riconoscere che un file è un file di testo con alcune sfumature in una codifica "errata". Ma come computer avrebbe bisogno di una sorta di intelligenza artificiale.

Si potrebbe sostenere che l'euristica di file è una sorta di intelligenza artificiale. Tuttavia, anche se lo è, è molto limitato.

Ecco ulteriori informazioni sul comando file: http://www.linfo.org/file_command.html

70
lesmana

Non è sempre possibile scoprire con certezza quale sia la codifica di un file di testo. Ad esempio, la sequenza di byte \303\275 (c3 bd in esadecimali) potrebbe essere ý in UTF-8 o ý in latino1 o Ă˝ in latino2 o in BIG-5 e così via.

Alcune codifiche hanno sequenze di byte non valide, quindi è possibile escluderle di sicuro. Ciò vale in particolare per UTF-8; la maggior parte dei testi nella maggior parte delle codifiche a 8 bit non sono valide UTF-8. Puoi verificare UTF-8 valido con isutf8 da moreutils o con iconv -f utf-8 -t utf-8 >/dev/null, tra gli altri.

Esistono strumenti che tentano di indovinare la codifica di un file di testo. Possono fare errori, ma spesso funzionano in pratica finché non si tenta deliberatamente di ingannarli.

  • file
  • Perl Encode::Guess (parte della distribuzione standard) prova le codifiche successive su una stringa di byte e restituisce la prima codifica in cui la stringa è un testo valido.
  • Enca è un indovinello e un convertitore di codifica. Puoi dargli un nome di lingua e un testo che presumi sia in quella lingua (le lingue supportate sono principalmente lingue dell'Europa orientale) e prova a indovinare la codifica.

Se sono presenti metadati (HTML/XML charset=, TeX \inputenc, emacs -*-coding-*-, ...) nel file, editor avanzati come Emacs o Vim sono spesso in grado di analizzare i metadati. Tuttavia, non è facile automatizzare dalla riga di comando.

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

È possibile utilizzare 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;"

Più preciso " mb_list_encodings ":

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 delle liste) che potrebbero corrispondere. Per ottenere risultati più accurati puoi 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

1
Mohamed23gharbi