Как я могу определить, является ли файл двоичным (не текстовым) в Python?
Я просматриваю большой набор файлов на Python и продолжаю получать совпадения в двоичных файлах. Это делает вывод невероятно беспорядочным.
Я знаю, что могу использовать grep -I
, но я делаю с данными больше, чем позволяет grep.
Раньше я просто искал символы старше 0x7f
, но utf8
и тому подобное, что делало это невозможным в современных системах. В идеале решение должно быть быстрым, но подойдет любое решение.
grep
сама использует для идентификации двоичных файлов, аналогична стратегии, опубликованной Хорхе Орпинелем ниже . Если вы не установите этот-z
параметр, он будет просто сканировать нулевой символ ("\000"
) в файле. С-z
, он сканирует файлы"\200"
. Заинтересованные и / или скептически настроенные могут проверить строку 1126 офgrep.c
. К сожалению, мне не удалось найти веб-страницу с исходным кодом, но, конечно, вы можете получить ее с gnu.org или через дистрибутив .git diff
и GNU, и GNUdiff
также используют одну и ту же стратегию. Я не уверен, настолько ли он распространен, потому что он намного быстрее и проще, чем альтернатива, или это просто из-за относительной редкости файлов UTF-16 в системах, в которых, как правило, установлены эти утилиты.Ответы:
Вы также можете использовать модуль mimetypes :
Составить список двоичных типов mime довольно просто. Например, Apache распространяется с файлом mime.types, который вы можете разобрать на набор списков, двоичных и текстовых, а затем проверить, есть ли mime в вашем текстовом или двоичном списке.
источник
mimetypes
использовать содержимое файла, а не только его имя?file
сообщает как «текст Unicode UTF-8 с очень длинными строками», но mimetypes.gest_type () вернет (None, None). Кроме того, список типов mimetype Apache является белым списком / подмножеством. Это далеко не полный список миметипов. Его нельзя использовать для классификации всех файлов как текстовых или нетекстовых.Еще один метод, основанный на поведении файла (1) :
Пример:
источник
bytearray([7,8,9,10,12,13,27]) + bytearray(range(0x20, 0x7f)) + bytearray(range(0x80, 0x100))
вместо него. См. Python, файл (1) - Почему числа [7,8,9,10,12,13,27] и диапазон (0x20, 0x100) используются для определения текста по сравнению с двоичным файлом и github.com/file/file/ blob /…0x7f
(DEL
).11
илиVT
? В таблице 11 рассматривается обычный текст ASCII, а это форматvertical tab
.Если вы используете python3 с utf-8, это просто, просто откройте файл в текстовом режиме и остановите обработку, если вы получите файл
UnicodeDecodeError
. Python3 будет использовать Unicode при работе с файлами в текстовом режиме (и bytearray в двоичном режиме) - если ваша кодировка не может декодировать произвольные файлы, вполне вероятно, что вы получитеUnicodeDecodeError
.Пример:
источник
with open(filename, 'r', encoding='utf-8') as f
напрямую?Если это помогает, многие двоичные типы начинаются с магических чисел. Вот список подписей файлов.
источник
Попробуй это:
источник
git diff
самом деле работает именно так , и, конечно же, он определяет файлы UTF-16 как двоичные.diff
тоже работает таким образом. Аналогичные проблемы возникают с файлами UTF-16.file
правильно определяет те же файлы, что и текст UTF-16. Я не проверялgrep
код, но он тоже определяет файлы UTF-16 как двоичные.file(1)
которые небезопасно печатать без преобразования, поэтому в данном случае подходит этот метод.Вот предложение, использующее команду файла Unix :
Пример использования:
У него есть недостатки, заключающиеся в том, что он не переносится в Windows (если у вас нет чего-то вроде этой
file
команды), и ему приходится создавать внешний процесс для каждого файла, что может быть неприятно.источник
file
как «Замороженная конфигурация Sendmail - версия m» - обратите внимание на отсутствие строки «текст». Возможно, использоватьfile -i
?Используйте библиотеку binaryornot ( GitHub ).
Это очень просто и основано на коде, найденном в этом вопросе о стеке.
На самом деле вы можете записать это в 2 строки кода, однако этот пакет избавляет вас от необходимости писать и тщательно тестировать эти 2 строки кода со всеми видами странных типов файлов, кроссплатформенными.
источник
Обычно приходится угадывать.
Вы можете рассматривать расширения как ключ к разгадке, если они есть в файлах.
Вы также можете распознавать известные двоичные форматы и игнорировать их.
В противном случае посмотрите, какая доля непечатаемых байтов ASCII у вас есть, и сделайте предположение.
Вы также можете попробовать декодировать из UTF-8 и посмотреть, дает ли это разумный результат.
источник
Более короткое решение с предупреждением UTF-16:
источник
for line in file
может потреблять неограниченное количество памяти, пока неb'\n'
будет найдено".read()"
возвращает здесь байтовую строку, которая является итерируемой (дает отдельные байты).Мы можем использовать сам python, чтобы проверить, является ли файл двоичным, потому что он не работает, если мы пытаемся открыть двоичный файл в текстовом режиме.
источник
Если вы не используете Windows, вы можете использовать Python Magic для определения типа файла. Затем вы можете проверить, является ли это типом text / mime.
источник
Вот функция, которая сначала проверяет, начинается ли файл со спецификации, и если нет, ищет нулевой байт в начальных 8192 байтах:
Технически проверка спецификации UTF-8 не нужна, потому что она не должна содержать нулевые байты для всех практических целей. Но поскольку это очень распространенная кодировка, быстрее проверять спецификацию в начале, чем сканировать все 8192 байта на предмет 0.
источник
Попробуйте использовать поддерживаемый в настоящее время python-magic, который не совпадает с модулем в ответе @Kami Kisiel. Это поддерживает все платформы, включая Windows, однако вам понадобятся
libmagic
двоичные файлы. Это объясняется в README.В отличие от модуля mimetypes , он не использует расширение файла и вместо этого проверяет содержимое файла.
источник
Я пришел сюда в поисках того же самого - комплексного решения, предоставляемого стандартной библиотекой для обнаружения двоичных файлов или текста. После просмотра вариантов, предложенных людьми, команда nix file выглядит лучшим выбором (я разрабатываю только для linux boxen). Некоторые другие опубликовали решения с использованием файла, но, на мой взгляд, они излишне сложны, поэтому вот что я придумал:
Само собой разумеется, что ваш код, который вызывает эту функцию, должен убедиться, что вы можете прочитать файл перед его тестированием, иначе это будет ошибочно определять файл как двоичный.
источник
Думаю, лучшим решением будет использование функции guess_type. Он содержит список с несколькими типами mimetype, и вы также можете включать свои собственные типы. Вот сценарий, который я написал для решения моей проблемы:
Он находится внутри класса, как вы можете видеть на основании структуры кода. Но вы можете в значительной степени изменить то, что хотите реализовать в своем приложении. Пользоваться им довольно просто. Метод getTextFiles возвращает объект списка со всеми текстовыми файлами, которые находятся в каталоге, который вы передаете в переменной пути.
источник
на * NIX:
Если у вас есть доступ к команде
file
оболочки, shlex может помочь сделать модуль подпроцесса более удобным:Или вы также можете вставить это в цикл for, чтобы получить вывод для всех файлов в текущем каталоге, используя:
или для всех подкаталогов:
источник
Большинство программ считают файл двоичным (то есть любым файлом, не ориентированным на строки), если он содержит символ NULL .
Вот версия Perl
pp_fttext()
(pp_sys.c
), реализованная на Python:Источник: Perl "угадать, является ли файл текстовым или двоичным", реализованный на Python.
источник
ты в юниксе? если да, то попробуйте:
Значения, возвращаемые оболочкой, инвертируются (0 - это нормально, поэтому, если он найдет «текст», он вернет 0, а в Python это выражение False).
источник
file
с-b
переключателем; он напечатает только тип файла без пути.is_binary_file = lambda filename: "text" in subprocess.check_output(["file", "-b", filename])
Более простой способ - проверить, состоит ли файл из символа NULL (
\x00
), используяin
оператор, например:См. Полный пример ниже:
Пример использования:
источник
Документация
источник