Вопрос или проблема
У меня есть несколько .htm
файлов, которые открываются в Gedit без каких-либо предупреждений или ошибок, но когда я открываю те же файлы в Jedit
, он предупреждает меня о недопустимом кодировании UTF-8…
HTML мета-тег указывает “charset=ISO-8859-1”. Jedit позволяет использовать Список запасных кодировок и Список автоопределителей кодировок (в настоящее время “BOM XML-PI”), так что моя непосредственная проблема была решена. Но это заставило меня задуматься: а что если метаданные отсутствуют?
Когда информация о кодировке просто недоступна, есть ли программа CLI, которая может сделать “наилучшую догадку” о том, какая кодировка может подойти?
И, хотя это немного другая проблема; есть ли программа CLI, которая проверяет корректность известной кодировки?
Команда file
делает “наилучшие догадки” о кодировке.
Здесь это продемонстрировано на файле, содержащем немецкий умлаут, закодированный в utf-8:
$ file umlaut-utf8.txt
umlaut-utf8.txt: UTF-8 Unicode text
(см. ниже, как я создал файлы)
Тот же умлаут в двух других кодировках:
$ file umlaut-iso88591.txt umlaut-utf16.txt
umlaut-iso88591.txt: ISO-8859 text
umlaut-utf16.txt: Little-endian UTF-16 Unicode text, with no line terminators
Все три вместе для недопустимой кодировки:
$ file umlaut-mixed.txt
umlaut-mixed.txt: data
Вы можете использовать параметр -i
для вывода в типе mime:
$ 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
(на mac это -I
, потому что разработчики Apple думают по-другому.)
Команда file
довольно ограничена. Она смотрит на некоторые байты и пытается угадать, какая кодировка может быть. Если она распознает паттерн, она скажет, что это та или иная кодировка. Если паттерн не распознается или если распознанные паттерны противоречат друг другу, она скажет “data” (или binary в типе mime). Что практически означает, что валидная кодировка не распознана.
Это похоже на то, как вы могли бы распознать текст как испанский или французский на основе распределения символов и умлаутов. Если вам был дан текст, в котором распределение символов не имеет смысла, вы могли бы заключить, что это “недопустимый” текст. Но это может быть язык, который вы просто раньше не видели. Сравните это с Lorem Ipsum. Текст, созданный для того, чтобы выглядеть как натуральный текст, но на самом деле является бессмыслицей: https://en.wikipedia.org/wiki/Lorem_ipsum
Вот пример, где file
не смог распознать правильную кодировку: просмотреть файл, содержащий текст DOS (символы рисования коробки, терминаторы строк CRLF) и escape-последовательности
Вот больше информации о команде file
: http://www.linfo.org/file_command.html
Как я создавал файлы:
$ echo ä > umlaut-utf8.txt
Вы можете скопировать эту строку и выполнить ее. Это должно создать файл, содержащий умлаут в utf8.
Проверьте шестнадцатеричный дамп:
$ hexdump -C umlaut-utf8.txt
00000000 c3 a4 0a |...|
00000003
Преобразуйте в другие кодировки:
$ iconv -f utf8 -t iso88591 umlaut-utf8.txt > umlaut-iso88591.txt
$ iconv -f utf8 -t utf16 umlaut-utf8.txt > umlaut-utf16.txt
Шестнадцатеричные дампы:
$ hexdump -C umlaut-iso88591.txt
00000000 e4 0a |..|
00000002
$ hexdump -C umlaut-utf16.txt
00000000 ff fe e4 00 0a 00 |......|
00000006
Сравнить с https://en.wikipedia.org/wiki/Ä#Computer_encoding
Создайте что-то “недопустимое”, смешав все три:
$ cat umlaut-iso88591.txt umlaut-utf8.txt umlaut-utf16.txt > umlaut-mixed.txt
Не всегда возможно точно узнать, какая кодировка у текстового файла. Например, последовательность байтов \303\275
(c3 bd
в шестнадцатеричном формате) может быть ý
в UTF-8, или ý
в latin1, или Ă˝
в latin2, или 羸
в BIG-5 и так далее.
Некоторые кодировки имеют недопустимые последовательности байтов, поэтому их можно точно исключить. Это особенно верно для UTF-8; большинство текстов в большинстве 8-битных кодировок не являются допустимыми UTF-8. Вы можете протестировать на допустимость UTF-8 с помощью isutf8
из moreutils или с помощью iconv -f utf-8 -t utf-8 >/dev/null
, среди прочих.
Существуют инструменты, которые пытаются угадать кодировку текстового файла. Они могут ошибаться, но обычно они работают на практике, если вы намеренно не пытаетесь их обмануть.
file
- Perl
Encode::Guess
(часть стандартной дистрибуции) пробует последовательные кодировки на байтовой строке и возвращает первую кодировку, в которой строка является допустимым текстом. - Enca — это гадалка кодировок и конвертер. Вы можете дать ей имя языка и текст, который вы предполагаете на этом языке (поддерживаемые языки в основном восточноевропейские языки), и она попытается угадать кодировку.
Если в файле есть метаданные (HTML/XML charset=
, TeX \inputenc
, emacs -*-coding-*-
и т.д.), то такие редакторы, как Emacs или Vim, часто могут разобрать эти метаданные. Однако это не легко автоматизировать с командной строки.
Я думаю, что этот инструмент CLI может сделать именно то, что вы искали!
Убедитесь, что у вас установлены Node.js и NPM:
$ sudo apt install nodejs npm
Установите CLI:
$ npm install -g detect-file-encoding-and-language
Используйте CLI:
$ dfeal "/home/user name/Documents/subtitle file.srt"
# Возможный результат: { language: french, encoding: CP1252, confidence: 0.99 }
Также в случае, если file -i дает вам unknown
Вы можете использовать эту 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
Ответ или решение
Как протестировать кодировку текстового файла: определение валидности и типа кодировки
Работа с текстовыми файлами в различных кодировках может создать определенные трудности, особенно если информация о кодировке отсутствует. В этой статье мы рассмотрим методы тестирования кодировки текстового файла, включая определение его валидности и определение типа кодировки. Мы также ознакомимся с несколькими эффективными инструментами, доступными как в командной строке (CLI), так и через программирование.
Основные понятия кодировки текстовых файлов
Кодировка определяет, как символы текста представлены в битах. Наиболее распространенные кодировки включают UTF-8, ISO-8859-1, UTF-16 и другие. Отсутствие информации о кодировке может привести к неправильному отображению текста, ложным предупреждениям о недопустимой кодировке или даже повреждению данных.
Как тестировать кодировку текстового файла
-
Использование команды
file
Команда
file
в Unix-подобных системах может помочь определить кодировку текстового файла. Она выполняет анализ байтов и делает "наилучшие предположения" о кодировке. Например:file имя_файла.txt
Использование параметра
-i
выводит результат в формате MIME:file -i имя_файла.txt
Пример вывода:
имя_файла.txt: text/plain; charset=utf-8
-
Проверка на валидность кодировки
Если вы знаете, какая кодировка должна использоваться, можно проверить её валидность. Например, для UTF-8 можно использовать
iconv
:iconv -f utf-8 -t utf-8 имя_файла.txt > /dev/null
Ошибки в этом процессе укажут на недопустимую кодировку.
Альтернативой является использование утилиты
isutf8
из пакета moreutils:isutf8 имя_файла.txt
-
Гадание кодировки с помощью специализированных инструментов
Существуют CLI-инструменты, способные догадаться о кодировке. Вот некоторые из них:
enca
— инструмент для угадывания кодировки, поддерживающий несколько языков, в основном восточноевропейских.DetectFileEncoding
— утилита на Node.js, позволяющая обнаруживать кодировку и язык файла:
npm install -g detect-file-encoding-and-language dfeal имя_файла.txt
-
Использование PHP для определения кодировки
Если у вас установлен PHP, вы можете использовать функции mbstring для определения кодировки:
php -r "echo mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ISO-8859-1');"
Чтобы получить результаты, используя все доступные кодировки:
php -r "echo mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings());"
Убедитесь, что установлено расширение PHP
mbstring
:apt-get install php-mbstring
Заключение
Тестирование кодировки текстового файла может быть затруднительным из-за многообразия кодировок и возможных недочетов в представлении текста. Используя описанные методы и инструменты, вы сможете эффективно определять и проверять кодировку ваших текстовых файлов. Если кодировка отсутствует или ситуация становится слишком сложной, не стесняйтесь использовать несколько методов вместе для получения наиболее точного результата.