Wie erkennt man automatisch die Kodierung von Textdateien?

69

Es gibt viele reine Textdateien, die in verschiedenen Zeichensätzen codiert wurden.

Ich möchte sie alle in UTF-8 konvertieren, aber bevor iconv ausgeführt wird, muss ich die ursprüngliche Codierung kennen. Die meisten Browser haben eine Auto DetectKodierungsoption. Ich kann diese Textdateien jedoch nicht einzeln prüfen, da zu viele vorhanden sind.

Erst nachdem ich die ursprüngliche Kodierung gekannt habe, kann ich die Texte nach konvertieren iconv -f DETECTED_CHARSET -t utf-8.

Gibt es ein Dienstprogramm zum Erkennen der Codierung von Nur-Text-Dateien? Es muss NICHT 100% perfekt sein, es macht mir nichts aus, wenn 100 Dateien in 1.000.000 Dateien falsch konvertiert sind.

Xiè Jìléi
quelle

Antworten:

57

Probieren Sie das Python-Modul chardet aus , das auf PyPi verfügbar ist:

pip install chardet

Dann lauf chardetect myfile.txt.

Chardet basiert auf dem Erkennungscode, der von Mozilla verwendet wird, und sollte daher angemessene Ergebnisse liefern, vorausgesetzt, der Eingabetext ist lang genug für statistische Analysen. Lesen Sie die Projektdokumentation .

Wie in den Kommentaren erwähnt, ist es recht langsam, aber einige Distributionen liefern auch die ursprüngliche C ++ - Version aus, wie @Xavier unter https://superuser.com/a/609056 gefunden hat . Irgendwo gibt es auch eine Java-Version.

Grawity
quelle
3
Ja, und es ist bereits wie python-chardetin Ubuntu Universum Repo verpackt .
Xiè Jìléi
Wenn es keine perfekte Vermutung war, chardetwird trotzdem die richtigste Vermutung abgegeben, wie ./a.txt: GB2312 (confidence: 0.99). Verglichen mit Enca, das gerade fehlgeschlagen ist und "Nicht erkannte Codierung" meldet. Läuft leider chardetsehr langsam.
Xiè Jìléi
1
@ 谢 谢 雷: Lass es über Nacht laufen oder so. Die Zeichensatzerkennung ist ein komplizierter Prozess . Sie können auch das Java-basierte jChardet ausprobieren oder ... das Original- Chardet ist Teil von Mozilla , es ist jedoch nur eine C ++ - Quelle verfügbar, kein Befehlszeilentool.
Grawity
2
Was die Geschwindigkeit betrifft: Laufen chardet <(head -c4000 filename.txt)war für meinen Anwendungsfall viel schneller und genauso erfolgreich. (falls es nicht klar ist, sendet diese Bash-Syntax nur die ersten 4000 Bytes an chardet)
ndemou
@ndemou habe ich chardet==3.0.4, und der tatsächliche Name der ausführbaren Datei des Befehlszeilentools ist chardetectnicht chardet.
Devy
32

Ich würde diesen einfachen Befehl verwenden:

encoding=$(file -bi myfile.txt)

Oder wenn Sie nur den tatsächlichen Zeichensatz möchten (wie utf-8):

encoding=$(file -b --mime-encoding myfile.txt)
Humpparitari
quelle
4
fileErkennt leider nur Kodierungen mit bestimmten Eigenschaften wie UTF-8 oder UTF-16. Der Rest - die alte ISO8859 oder ihre MS-DOS- und Windows-Korrespondenten - wird als "unknown-8bit" oder ähnliches aufgeführt, selbst für Dateien, die chardetmit 99% iger Sicherheit erkannt werden .
Grawity
6
Datei zeigte mir
ISO
Was ist, wenn die Erweiterung lügt?
james.garriss
2
@ james.garriss: Dateierweiterung hat nichts mit der (Text-) Inhaltscodierung zu tun.
MestreLion
29

Unter Debian-basierten Linux bietet das uchardet- Paket ( Debian / Ubuntu ) ein Befehlszeilentool. Siehe unten die Paketbeschreibung:

 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
Xavier
quelle
3
Vielen Dank! Auf der Homepage des Projekts war mir nicht klar, dass eine CLI enthalten war. Es ist auch unter OS X verfügbar, wenn es uchardetüber Homebrew installiert wird.
Stefan Schmidt
1
Anfangs war ich ein wenig verwirrt, weil ein ISO 8859-1-Dokument fälschlicherweise als Windows-1252 identifiziert wurde, aber im druckbaren Bereich ist Windows-1252 eine Obermenge von ISO 8859-1, sodass die Konvertierung mit problemlos iconvfunktioniert.
Stefan Schmidt
16

Für Linux gibt es enca und für Solaris können Sie auto_ef verwenden .

cularis
quelle
Enca scheint mir zu streng: enca -d -L zh ./a.txtfehlgeschlagen mit Meldung ./a.txt: Unrecognized encoding Failure reason: No clear winner.Wie bei @grawity erwähnt, chardetist es lockerer, allerdings ist es noch zu langsam.
Xiè Jìléi
10
Enca hat den Test "Tatsächlich etwas" komplett nicht bestanden.
Michael Wolf
1
uchardet ist fehlgeschlagen (CP1252 anstelle des eigentlichen CP1250 erkannt), aber enca hat einwandfrei funktioniert. (einzelnes Beispiel, schwer zu verallgemeinern ...)
Palo
2

Zurück zu chardet (Python 2.?) Reicht dieser Aufruf möglicherweise aus:

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

Obwohl es alles andere als perfekt ist ...

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

Für diejenigen, die regelmäßig Emacs verwenden, ist möglicherweise Folgendes hilfreich (ermöglicht die manuelle Überprüfung und Validierung der Transfomation).

Außerdem stelle ich häufig fest, dass die automatische Erkennung von Emacs-Zeichensätzen wesentlich effizienter ist als die anderen Tools zur automatischen Erkennung von Zeichensätzen (z. B. 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)
  )

Dann erledigt ein einfacher Aufruf von Emacs mit diesem Skript als Argument (siehe die Option "-l") den Job.

Yves Lhuillier
quelle
0

isutf8(aus dem moreutilsPaket) hat den Job gemacht

Ronan
quelle
2
Wie? Diese Antwort ist nicht wirklich hilfreich.
Moses
1
Es wurde nicht genau gefragt, ist aber ein nützliches Werkzeug. Wenn die Datei UTF-8-gültig ist, ist der Beendigungsstatus Null. Wenn die Datei nicht UTF-8-gültig ist oder ein Fehler vorliegt, ist der Beendigungsstatus ungleich Null.
Tonne
0

Auch für den Fall, dass Sie Datei -i gibt Ihnen unbekannt

Sie können diesen PHP-Befehl verwenden, der den folgenden Zeichensatz erraten kann:

In PHP können Sie wie folgt überprüfen:

Codierungsliste explizit angeben:

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

Genauere " mb_list_encodings ":

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

Hier im ersten Beispiel sehen Sie, dass ich eine Liste von Codierungen (Erkennungslistenreihenfolge) erstellt habe, die möglicherweise übereinstimmen. Um genauere Ergebnisse zu erhalten, können Sie alle möglichen Kodierungen verwenden: mb_list_encodings ()

Hinweis Für mb_ * -Funktionen ist php-mbstring erforderlich

apt-get install php-mbstring 

Siehe Antwort: https://stackoverflow.com/a/57010566/3382822

Mohamed23gharbi
quelle