Як автоматично виявити кодування текстових файлів?


69

Є багато простих текстових файлів, кодованих у варіантах діаграм.

Я хочу перетворити їх усіх у UTF-8, але перш ніж запустити iconv, мені потрібно знати його оригінальне кодування. У більшості браузерів є Auto Detectможливість кодування, однак я не можу перевірити ці текстові файли по одному, оскільки їх занадто багато.

Тільки знаючи оригінальне кодування, я потім можу перетворити тексти iconv -f DETECTED_CHARSET -t utf-8.

Чи є утиліта для виявлення кодування простих текстових файлів? ЦЕ НЕ повинно бути 100% досконалим, я не заперечую, якщо 100 файлів неправильно перетворено в 1 000 000 файлів.

Відповіді:


57

Спробуйте модуль chardet Python, який доступний на PyPi:

pip install chardet

Потім бігайте chardetect myfile.txt.

Шардет заснований на коді виявлення, який використовує Mozilla, тому він повинен дати розумні результати за умови, що вхідний текст достатньо довгий для статистичного аналізу. Читай проектну документацію .

Як згадується в коментарях, це досить повільно, але деякі дистрибутиви також постачають оригінальну версію C ++, як @Xavier знайшов у https://superuser.com/a/609056 . Десь також є версія Java.


3
Так, і це вже упаковано, як python-chardetу Rebu Unipo Unipo.
Xiè Jìléi

Якщо це не було ідеальною здогадкою, chardetвсе одно дамо найбільш вірну здогадку, як ./a.txt: GB2312 (confidence: 0.99). У порівнянні з Enca, яка щойно не вдалася, і повідомляє про "Нерозпізнане кодування". Однак, на жаль, chardetпрацює дуже повільно.
Xiè Jìléi

1
@ 谢 继 雷: Запустити її протягом ночі чи щось подібне. Виявлення Charset є складним процесом . Ви також можете спробувати jChardet на базі Java або ... оригінальний шардет є частиною Mozilla , але доступне лише джерело C ++, не існує інструменту командного рядка.
grawity

2
Щодо швидкості: біг chardet <(head -c4000 filename.txt)був набагато швидшим і однаково вдалим для мого використання. (якщо не зрозуміло, цей синтаксис bash надішле в chardet лише перші 4000 байт)
ndemou

@ndemou У мене є chardet==3.0.4, а власне виконане ім'я інструменту командного рядка - chardetectні chardet.
Devy

31

Я використовував би цю просту команду:

encoding=$(file -bi myfile.txt)

Або якщо ви хочете просто фактичний набір символів (як utf-8):

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

4
На жаль, fileвиявляє лише кодування із специфічними властивостями, такими як UTF-8 або UTF-16. Решта - старенький ISO8859 або їх кореспонденти MS-DOS та Windows - вказані як "невідомі 8bit" або щось подібне, навіть для файлів, які chardetвиявляють з 99% впевненістю.
grawity

6
файл показав мені iso-8859-1
cweiske

Що робити, якщо розширення лежить?
james.garriss

2
@ james.garriss: розширення файлу не має нічого спільного з кодуванням (текстового) вмісту.
MestreLion

29

На базі Debian Linux пакет uchardet ( Debian / Ubuntu ) забезпечує інструмент командного рядка. Дивіться нижче опис упаковки:

 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
Дякую! З домашньої сторінки проекту мені не було очевидно, що є CLI. Він також доступний в OS X при установці uchardetчерез Homebrew.
Штефан Шмідт

1
Спочатку я трохи заплутався, тому що документ ISO 8859-1 був помилково ідентифікований як Windows-1252, але в діапазоні для друку Windows-1252 є супернабір ISO 8859-1, тому конверсія iconvпрацює з чудовими можливостями.
Штефан Шмідт

16

Для Linux існує enca, а для Solaris ви можете використовувати auto_ef .


Енка видається мені занадто суворою: enca -d -L zh ./a.txtне вдалося з повідомленням ./a.txt: Unrecognized encoding Failure reason: No clear winner.Як згадував @grawity, chardetвін більш млявий , проте все ще занадто повільний.
Xiè Jìléi

10
Енка повністю провалює тест "насправді щось робить".
Майкл Вольф

1
uchardet не вдався (виявлено CP1252 замість фактичного CP1250), але enca працював чудово. (єдиний приклад, важко узагальнити ...)
Пало


2

Повернення до chardet (python 2.?) Цього дзвінка може бути достатньо:

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

Хоча це далеко не ідеально….

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

Для тих, хто регулярно використовує Emacs, вони можуть знайти наступне корисне (дозволяє перевірити та перевірити трансформацію вручну).

Крім того, я часто виявляю, що автоматичне виявлення Emacs char-set набагато ефективніше, ніж інші засоби автоматичного виявлення char-set (наприклад, 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)
  )

Потім простий дзвінок до Emacs з цим скриптом як аргумент (див. Опцію "-l") виконує цю роботу.



0

isutf8moreutilsпакета) зробив роботу


2
Як? Ця відповідь не дуже корисна.
Мойсей

1
Це не точно запитали, але це корисний інструмент. Якщо файл дійсний UTF-8, стан виходу дорівнює нулю. Якщо файл недійсний UTF-8 або є помилка, стан виходу не дорівнює нулю.
т.

0

Також у випадку, якщо ви подаєте файл -i, вам невідомо

Ви можете скористатися цією командою php, яка може здогадатися, як описано нижче:

У php ви можете перевірити як нижче:

Вказання списку кодування явно:

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

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

Тут у першому прикладі ви бачите, що я помістив список кодувань (виявити порядок списку), які можуть відповідати. Для отримання більш точного результату ви можете використовувати всі можливі кодування через: mb_list_encodings ()

Примітка. Функції mb_ * вимагають php-mbstring

apt-get install php-mbstring 

Дивіться відповідь: https://stackoverflow.com/a/57010566/3382822

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.