Bagaimana cara mendeteksi penyandian file teks secara otomatis?

69

Ada banyak file teks biasa yang dikodekan dalam rangkaian varian.

Saya ingin mengonversikan semuanya menjadi UTF-8, tetapi sebelum menjalankan ikonv, saya perlu mengetahui penyandian aslinya. Sebagian besar browser memiliki Auto Detectopsi dalam penyandian, namun, saya tidak dapat memeriksa file teks itu satu per satu karena ada terlalu banyak.

Hanya setelah mengetahui pengodean asli, saya kemudian dapat mengonversi teks dengan iconv -f DETECTED_CHARSET -t utf-8.

Apakah ada utilitas untuk mendeteksi penyandian file teks biasa? TIDAK HARUS 100% sempurna, saya tidak keberatan jika ada 100 file yang salah dikonversi dalam 1.000.000 file.

Xiè Jìléi
sumber

Jawaban:

57

Coba modul Python chardet , yang tersedia di PyPi:

pip install chardet

Kemudian jalankan chardetect myfile.txt.

Chardet didasarkan pada kode deteksi yang digunakan oleh Mozilla, sehingga harus memberikan hasil yang wajar, asalkan teks input cukup panjang untuk analisis statistik. Baca dokumentasi proyek .

Seperti disebutkan dalam komentar, ini cukup lambat, tetapi beberapa distribusi juga mengirimkan versi C ++ asli seperti yang ditemukan oleh @Xavier di https://superuser.com/a/609056 . Ada juga versi Java di suatu tempat.

grawity
sumber
3
Ya, dan itu sudah dikemas seperti python-chardetdalam repo alam semesta Ubuntu.
Xiè Jìléi
Jika itu bukan tebakan yang sempurna, chardetmasih akan memberikan tebakan yang paling benar ./a.txt: GB2312 (confidence: 0.99). Dibandingkan dengan Enca yang baru saja gagal dan melaporkan 'Pengodean tidak dikenal'. Namun, sayangnya, chardetberjalan sangat lambat.
Xiè Jìléi
1
@ 谢 继 雷: Apakah berjalan semalam atau semacamnya. Deteksi charset adalah suatu proses yang rumit . Anda juga dapat mencoba jChardet berbasis Java atau ... chardet asli adalah bagian dari Mozilla , tetapi hanya sumber C ++ yang tersedia, tanpa alat baris perintah.
grawity
2
Mengenai kecepatan: berlari chardet <(head -c4000 filename.txt)jauh lebih cepat dan sama-sama sukses untuk kasus penggunaan saya. (kalau-kalau tidak jelas sintaks bash ini hanya akan mengirimkan 4000 byte pertama ke chardet)
ndemou
@ Saya sudah chardet==3.0.4, dan nama yang dapat dieksekusi alat baris perintah sebenarnya chardetecttidak chardet.
Devy
32

Saya akan menggunakan perintah sederhana ini:

encoding=$(file -bi myfile.txt)

Atau jika Anda ingin hanya set karakter aktual (seperti utf-8):

encoding=$(file -b --mime-encoding myfile.txt)
Humpparitari
sumber
4
Sayangnya, filehanya mendeteksi pengkodean dengan properti tertentu, seperti UTF-8 atau UTF-16. Sisanya - ISO8859 tua atau koresponden MS-DOS dan Windows - terdaftar sebagai "tidak diketahui-8bit" atau yang serupa, bahkan untuk file yang chardetmendeteksi dengan 99% kepercayaan.
grawity
6
file menunjukkan kepada saya iso-8859-1
cweiske
Bagaimana jika ekstensi itu bohong?
james.garriss
2
@ james.garriss: ekstensi file tidak ada hubungannya dengan penyandian konten (teks).
MestreLion
29

Pada Linux berbasis Debian, paket uchardet ( Debian / Ubuntu ) menyediakan alat baris perintah. Lihat di bawah deskripsi paket:

 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
sumber
3
Terima kasih! Dari beranda proyek, tidak jelas bagi saya bahwa ada CLI yang disertakan. Ini juga tersedia di OS X saat menginstal uchardetmelalui Homebrew.
Stefan Schmidt
1
Saya agak bingung pada awalnya karena dokumen ISO 8859-1 salah diidentifikasi sebagai Windows-1252 tetapi dalam rentang yang dapat dicetak Windows-1252 adalah superset dari ISO 8859-1 sehingga konversi dengan iconvberfungsi dengan baik.
Stefan Schmidt
16

Untuk Linux, ada enca dan untuk Solaris Anda dapat menggunakan auto_ef .

cularis
sumber
Enca tampaknya terlalu ketat bagi saya: enca -d -L zh ./a.txtgagal dengan pesan ./a.txt: Unrecognized encoding Failure reason: No clear winner.Seperti yang disebutkan @grawity, chardetlebih longgar, namun terlalu lambat.
Xiè Jìléi
10
Enca sepenuhnya gagal dalam tes "benar-benar melakukan sesuatu".
Michael Wolf
1
uchardet gagal (mendeteksi CP1252 bukan CP1250 yang sebenarnya), tetapi enca bekerja dengan baik (contoh tunggal, sulit digeneralisasi ...)
Palo
2

Kembali ke chardet (python 2.?) Panggilan ini mungkin cukup:

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

Meskipun jauh dari sempurna ....

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
sumber
2

Bagi mereka yang secara teratur menggunakan Emacs, mereka mungkin menemukan hal-hal berikut yang berguna (memungkinkan untuk memeriksa dan memvalidasi secara manual transfomasi).

Selain itu saya sering menemukan bahwa deteksi otomatis char-set Emacs jauh lebih efisien daripada alat deteksi otomatis char-set lainnya (seperti 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)
  )

Kemudian, panggilan sederhana ke Emacs dengan skrip ini sebagai argumen (lihat opsi "-l") melakukan pekerjaan.

Yves Lhuillier
sumber
0

isutf8(dari moreutilspaket) melakukan pekerjaan

Ronan
sumber
2
Bagaimana? Jawaban ini tidak terlalu membantu.
Moses
1
Ini tidak ditanyakan, tetapi merupakan alat yang berguna. Jika file tersebut valid UTF-8, status keluar adalah nol. Jika file tidak valid UTF-8, atau ada beberapa kesalahan, status keluar tidak nol.
ton
0

Juga jika Anda mengajukan -i memberi Anda diketahui

Anda dapat menggunakan perintah php ini yang dapat menebak charset seperti di bawah ini:

Di php Anda dapat memeriksa seperti di bawah ini:

Menentukan daftar penyandian secara eksplisit:

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 " lebih akurat :

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

Di sini, di contoh pertama, Anda dapat melihat bahwa saya meletakkan daftar penyandian (deteksi urutan daftar) yang mungkin cocok. Untuk mendapatkan hasil yang lebih akurat, Anda dapat menggunakan semua kemungkinan penyandian melalui: mb_list_encodings ()

Catatan fungsi mb_ * membutuhkan php-mbstring

apt-get install php-mbstring 

Lihat jawaban: https://stackoverflow.com/a/57010566/3382822

Mohamed23gharbi
sumber