[python] 파이썬에서 파일이 바이너리 (비 텍스트)인지 어떻게 감지 할 수 있습니까?

파이썬에서 파일이 바이너리 (텍스트가 아닌)인지 어떻게 알 수 있습니까?

파이썬에서 큰 파일 집합을 검색하고 있으며 이진 파일에서 계속 일치 항목을 얻습니다. 이것은 출력이 엄청나게 지저분하게 보입니다.

을 사용할 수 있다는 것을 알고 grep -I있지만 grep이 허용하는 것보다 더 많은 데이터를 사용하고 있습니다.

과거에, 난 그냥 이상의 문자를 검색 할 것이다 0x7f, 그러나 utf8와 같은은 현대적인 시스템이 불가능합니다. 이상적으로 솔루션은 빠르지 만 모든 솔루션이 가능합니다.



답변

mimetypes 모듈을 사용할 수도 있습니다 .

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

바이너리 MIME 유형 목록을 컴파일하는 것은 매우 쉽습니다. 예를 들어 Apache는 목록, 바이너리 및 텍스트 세트로 구문 분석 할 수있는 mime.types 파일과 함께 배포 한 다음 mime이 텍스트 또는 바이너리 목록에 있는지 확인합니다.


답변

file (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


답변

utf-8과 함께 python3을 사용하는 경우 간단합니다. 텍스트 모드에서 파일을 열고 UnicodeDecodeError. Python3은 텍스트 모드 (및 바이너리 모드에서는 바이트 배열)에서 파일을 처리 할 때 유니 코드를 사용합니다. 인코딩이 임의의 파일을 디코딩 할 수없는 경우 UnicodeDecodeError.

예:

try:
    with open(filename, "r") as f:
        for l in f:
             process_line(l)
except UnicodeDecodeError:
    pass # Fond non-text data


답변

도움이된다면 많은 이진 유형이 매직 넘버로 시작됩니다. 다음은 파일 서명 목록 입니다.


답변

이 시도:

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


답변

다음은 Unix 파일 명령 을 사용하는 제안입니다 .

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')
진실
>>> istext ( '/ vmlinuz')
그릇된
>>> 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') # UTF-8에서 작동합니다.
진실

Windows로 이식 할 수 없다는 단점이 있으며 ( file명령어 와 같은 것이없는 경우), 각 파일에 대해 외부 프로세스를 생성해야하므로 맛이 좋지 않을 수 있습니다.


답변

사용 binaryornot의 라이브러리 ( GitHub의 ).

이것은 매우 간단하며이 stackoverflow 질문에서 찾은 코드를 기반으로합니다.

실제로 2 줄의 코드로 작성할 수 있지만,이 패키지를 사용하면 모든 종류의 이상한 파일 유형 인 크로스 플랫폼으로 2 줄의 코드를 작성하고 철저하게 테스트 할 필요가 없습니다.