Как автоматически определить кодировку текстового файла?

69

Есть много простых текстовых файлов, которые были закодированы в различных кодировках.

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

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

Есть ли какая-нибудь утилита для определения кодировки простых текстовых файлов? Это не обязательно должно быть на 100% идеально, я не возражаю, если в 1 000 000 файлов было неправильно преобразовано 100 файлов.

Xiè Jìléi
источник

Ответы:

57

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

pip install chardet

Тогда беги chardetect myfile.txt.

Chardet основан на коде обнаружения, используемом Mozilla, поэтому он должен давать разумные результаты при условии, что входной текст достаточно длинный для статистического анализа. Прочитайте проектную документацию .

Как упоминалось в комментариях, это довольно медленно, но некоторые дистрибутивы также поставляют оригинальную версию C ++, которую @Xavier нашел в https://superuser.com/a/609056 . Где-то есть и версия на Java.

grawity
источник
3
Да, и он уже упакован, как python-chardetв репозитории Ubuntu Universe.
Xiè Jìléi
Если это не было идеальное предположение, chardetвсе равно даст наиболее правильное предположение, как ./a.txt: GB2312 (confidence: 0.99). По сравнению с Enca, которая только что потерпела неудачу и сообщает «Нераспознанная кодировка». Однако, к сожалению, chardetработает очень медленно.
Xiè Jìléi
1
@ 谢 继 雷: Запустите его на ночь или что-то в этом роде. Обнаружение Charset является сложным процессом . Вы также можете попробовать jChardet на основе Java или ... оригинальный chardet является частью Mozilla , но доступен только исходный код C ++, без инструмента командной строки.
grawity
2
Что касается скорости: бег chardet <(head -c4000 filename.txt)был намного быстрее и одинаково успешен для моего варианта использования. (если неясно, этот синтаксис bash будет отправлять только первые 4000 байтов в chardet)
ndemou
@ndemou У меня есть chardet==3.0.4, а фактическое имя исполняемого файла инструмента командной строки - chardetectнет chardet.
Деви
32

Я бы использовал эту простую команду:

encoding=$(file -bi myfile.txt)

Или, если вы хотите просто фактический набор символов (например utf-8):

encoding=$(file -b --mime-encoding myfile.txt)
Humpparitari
источник
4
К сожалению, fileобнаруживает только кодировки с определенными свойствами, такими как UTF-8 или UTF-16. Остальные - устаревшие ISO8859 или их корреспонденты MS-DOS и Windows - перечислены как «unknown-8bit» или что-то подобное, даже для файлов, которые chardetобнаруживают с вероятностью 99%.
grawity
6
файл показал мне iso-8859-1
cweiske
Что делать, если расширение лжет?
james.garriss
2
@ james.garriss: расширение файла не имеет ничего общего с его (текстовым) кодированием содержимого.
MestreLion
29

В Linux на основе Debian пакет 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 .

cularis
источник
Enca кажется слишком строгим для меня: ошибка 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'}
estani
источник
2

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

Более того, я часто нахожу, что автоопределение набора символов в Emacs гораздо более эффективно, чем другие инструменты автоопределения набора символов (такие как 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

isutf8(из moreutilsпакета) сделал работу

Ронан
источник
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

Mohamed23gharbi
источник