Как я могу определить, является ли файл двоичным (нетекстовым) в Python? - PullRequest
88 голосов
/ 22 мая 2009

Как узнать, является ли файл двоичным (нетекстовым) в python? Я ищу большой набор файлов в Python и продолжаю получать совпадения в двоичных файлах. Это делает вывод выглядеть невероятно грязным.

Я знаю, что могу использовать grep -I, но я делаю с данными больше, чем позволяет grep.

В прошлом я бы просто искал символы больше 0x7f, но utf8 и тому подобное сделали это невозможным в современных системах. В идеале решение будет быстрым, но подойдет любое решение.

Ответы [ 19 ]

52 голосов
/ 12 сентября 2011

Еще один метод , основанный на поведении файла (1) :

>>> textchars = bytearray({7,8,9,10,12,13,27} | set(range(0x20, 0x100)) - {0x7f})
>>> is_binary_string = lambda bytes: bool(bytes.translate(None, textchars))

Пример:

>>> is_binary_string(open('/usr/bin/python', 'rb').read(1024))
True
>>> is_binary_string(open('/usr/bin/dh_python3', 'rb').read(1024))
False
37 голосов
/ 22 мая 2009

Вы также можете использовать модуль mimetypes :

import mimetypes
...
mime = mimetypes.guess_type(file)

Довольно просто составить список бинарных типов пантомимы. Например, Apache распространяет файл mime.types, который можно проанализировать в виде набора списков, двоичного и текстового, а затем проверить, есть ли mime в вашем текстовом или двоичном списке.

10 голосов
/ 09 июня 2010

Попробуйте это:

def is_binary(filename):
    """Return true if the given filename is binary.
    @raise EnvironmentError: if the file does not exist or cannot be accessed.
    @attention: found @ http://bytes.com/topic/python/answers/21222-determine-file-type-binary-text on 6/08/2010
    @author: Trent Mick <TrentM@ActiveState.com>
    @author: Jorge Orpinel <jorge@orpinel.com>"""
    fin = open(filename, 'rb')
    try:
        CHUNKSIZE = 1024
        while 1:
            chunk = fin.read(CHUNKSIZE)
            if '\0' in chunk: # found null byte
                return True
            if len(chunk) < CHUNKSIZE:
                break # done
    # A-wooo! Mira, python no necesita el "except:". Achis... Que listo es.
    finally:
        fin.close()

    return False
9 голосов
/ 16 мая 2015

Если вы используете python3 с utf-8, это просто, просто откройте файл в текстовом режиме и остановите обработку, если вы получите UnicodeDecodeError. Python3 будет использовать Unicode при обработке файлов в текстовом режиме (и bytearray в двоичном режиме) - если ваша кодировка не может декодировать произвольные файлы, вполне вероятно, что вы получите UnicodeDecodeError.

Пример:

try:
    with open(filename, "r") as f:
        for l in f:
             process_line(l)
except UnicodeDecodeError:
    pass # Fond non-text data
8 голосов
/ 22 мая 2009

Если это поможет, многие многие двоичные типы начинаются с магических чисел. Вот список подписей файлов.

6 голосов
/ 22 мая 2009

Вот предложение, которое использует команду Unix file :

import re
import subprocess

def istext(path):
    return (re.search(r':.* text',
                      subprocess.Popen(["file", '-L', path], 
                                       stdout=subprocess.PIPE).stdout.read())
            is not None)

Пример использования:

>>> istext('/etc/motd') 
True
>>> istext('/vmlinuz') 
False
>>> open('/tmp/japanese').read()
'\xe3\x81\x93\xe3\x82\x8c\xe3\x81\xaf\xe3\x80\x81\xe3\x81\xbf\xe3\x81\x9a\xe3\x81\x8c\xe3\x82\x81\xe5\xba\xa7\xe3\x81\xae\xe6\x99\x82\xe4\xbb\xa3\xe3\x81\xae\xe5\xb9\x95\xe9\x96\x8b\xe3\x81\x91\xe3\x80\x82\n'
>>> istext('/tmp/japanese') # works on UTF-8
True

У него есть недостатки: его нельзя переносить в Windows (если только у вас там нет команды типа file) и что для каждого файла требуется запуск внешнего процесса, который может быть неприемлемым.

5 голосов
/ 07 ноября 2014

Использовать библиотеку binaryornot ( GitHub ).

Это очень просто и основано на коде, найденном в этом вопросе stackoverflow.

Вы можете написать это в 2 строки кода, однако этот пакет избавляет вас от необходимости писать и тщательно тестировать эти 2 строки кода со всеми видами странных типов файлов, кросс-платформенными.

4 голосов
/ 22 мая 2009

Обычно вы должны угадать.

Вы можете рассматривать расширения как одну подсказку, если они есть в файлах.

Вы также можете распознавать известные двоичные форматы и игнорировать их.

В противном случае посмотрите, какая доля непечатных ASCII-байтов у вас есть, и сделайте из этого предположение.

Вы также можете попробовать декодирование из UTF-8 и посмотреть, дает ли это ощутимый вывод.

3 голосов
/ 03 июля 2012

Более короткое решение с предупреждением UTF-16:

def is_binary(filename):
    """ 
    Return true if the given filename appears to be binary.
    File is considered to be binary if it contains a NULL byte.
    FIXME: This approach incorrectly reports UTF-16 as binary.
    """
    with open(filename, 'rb') as f:
        for block in f:
            if b'\0' in block:
                return True
    return False
3 голосов
/ 23 мая 2009

Если вы не в Windows, вы можете использовать Python Magic для определения типа файла. Затем вы можете проверить, является ли это тип текста / пантомимы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...