ฉันจะตรวจสอบได้อย่างไรว่าไฟล์เป็นไบนารี (ไม่ใช่ข้อความ) ใน python


105

ฉันจะทราบได้อย่างไรว่าไฟล์เป็นไบนารี (ไม่ใช่ข้อความ) ใน python

ฉันกำลังค้นหาไฟล์ชุดใหญ่ใน python และทำการจับคู่ไฟล์ไบนารีต่อไป สิ่งนี้ทำให้ผลลัพธ์ดูยุ่งเหยิงอย่างไม่น่าเชื่อ

ฉันรู้ว่าฉันสามารถใช้ได้grep -Iแต่ฉันใช้ข้อมูลมากกว่าที่ grep อนุญาต

ที่ผ่านมาฉันแค่ค้นหาตัวละครที่มากกว่า0x7fแต่utf8ในทำนองเดียวกันทำให้สิ่งนั้นเป็นไปไม่ได้ในระบบสมัยใหม่ ตามหลักการแล้วการแก้ปัญหาจะรวดเร็ว แต่วิธีแก้ปัญหาใด ๆ จะทำ


IF "ในอดีตฉันเพิ่งค้นหาอักขระที่มากกว่า 0x7f" แล้วคุณเคยทำงานกับข้อความ ASCII ธรรมดาก็ยังไม่มีปัญหาเนื่องจากข้อความ ASCII ที่เข้ารหัสเป็น UTF-8 ยังคงเป็น ASCII (เช่นไม่มีไบต์> 127)
tzot

@ ΤΖΩΤΖΙΟΥ: จริง แต่ฉันบังเอิญรู้ว่าไฟล์บางไฟล์ที่ฉันกำลังจัดการอยู่คือ utf8 ฉันหมายถึงเคยชินในความหมายทั่วไปไม่ใช่ในความหมายเฉพาะของไฟล์เหล่านี้ :)
เสียใจ

1
ด้วยความน่าจะเป็นเท่านั้น คุณสามารถตรวจสอบว่า: 1) ไฟล์มี \ n 2) จำนวนไบต์ระหว่าง \ n ค่อนข้างน้อย (ไม่น่าเชื่อถือ) l 3) ไฟล์ไม่ได้ไบต์ที่มีค่าน้อยกว่าค่าของอักขระ "space" ของ ASCCI ('' ) - ยกเว้น "\ n" "\ r" "\ t" และศูนย์
SigTerm

3
กลยุทธ์ว่าgrepตัวเองใช้ในการระบุไฟล์ไบนารีจะคล้ายกับที่โพสต์โดย Jorge Orpinel ด้านล่าง เว้นแต่คุณจะตั้งค่า-zตัวเลือกมันจะสแกนหาอักขระ null ( "\000") ในไฟล์ ด้วยก็จะสแกนหา-z "\200"ผู้ที่สนใจและ / หรือสงสัยสามารถตรวจสอบสาย 1126 grep.cของ ขอโทษนะฉันไม่สามารถพบหน้าเว็บที่มีรหัสที่มา แต่แน่นอนคุณจะได้รับจากgnu.orgหรือผ่านทางdistro
สังหรณ์ใจ

3
ป.ล. ตามที่กล่าวไว้ในเธรดความคิดเห็นสำหรับโพสต์ของ Jorge กลยุทธ์นี้จะให้ผลบวกที่ผิดพลาดสำหรับไฟล์ที่มีเช่นข้อความ UTF-16 อย่างไรก็ตามทั้งสองgit diffและ GNU diffยังใช้กลยุทธ์เดียวกัน ฉันไม่แน่ใจว่ามันแพร่หลายมากหรือเปล่าเพราะมันเร็วและง่ายกว่าทางเลือกอื่นมากหรือว่าเป็นเพียงเพราะความหายากสัมพัทธ์ของไฟล์ UTF-16 ในระบบซึ่งมักจะมีการติดตั้งยูทิลิตี้เหล่านี้
สังหรณ์ใจ

คำตอบ:


42

คุณยังสามารถใช้โมดูลmimetypes :

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

การรวบรวมรายการประเภท mime ไบนารีค่อนข้างง่าย ตัวอย่างเช่น Apache กระจายด้วยไฟล์ mime.types ที่คุณสามารถแยกวิเคราะห์เป็นชุดของรายการไบนารีและข้อความจากนั้นตรวจสอบเพื่อดูว่า mime อยู่ในรายการข้อความหรือไบนารีของคุณหรือไม่


16
มีวิธีในmimetypesการใช้เนื้อหาของไฟล์มากกว่าชื่อไฟล์หรือไม่?
สังหรณ์ใจ

4
@intuited ไม่ใช่ แต่ libmagic ทำอย่างนั้น ใช้มันผ่านหลามมายากล
Bengt

มีคำถามที่คล้ายกันกับคำตอบที่ดีที่นี่: stackoverflow.com/questions/1446549/… คำตอบตามสูตร activestate ดูดีสำหรับฉันมันอนุญาตให้มีอักขระที่ไม่สามารถพิมพ์ได้ในสัดส่วนเล็กน้อย (แต่ไม่มี \ 0 สำหรับบางคน เหตุผล).
Sam Watkins

5
นี่ไม่ใช่คำตอบที่ดีเพียงเพราะโมดูล mimetypes ไม่ดีสำหรับทุกไฟล์ ตอนนี้ฉันกำลังดูไฟล์ที่ระบบfileรายงานว่าเป็น "UTF-8 Unicode text ที่มีบรรทัดยาวมาก" แต่ mimetypes.gest_type () จะส่งคืน (None, None) นอกจากนี้รายการ mimetype ของ Apache ยังเป็นรายการที่อนุญาตพิเศษ / ชุดย่อย มันไม่ได้เป็นรายการประเภทที่ไม่สมบูรณ์ ไม่สามารถใช้เพื่อจำแนกไฟล์ทั้งหมดเป็นข้อความหรือไม่ใช่ข้อความ
Purrell

1
guess_types ขึ้นอยู่กับนามสกุลไฟล์ไม่ใช่เนื้อหาจริงตามที่คำสั่ง Unix "file" จะทำ
Eric H.

61

อีกวิธีหนึ่งตามลักษณะการทำงานของไฟล์ (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

สามารถรับได้ทั้งเชิงลบบวกเท็จและเท็จ แต่ก็ยังเป็นวิธีการที่ชาญฉลาดที่ใช้ได้กับไฟล์ส่วนใหญ่ +1.
สเปกตรัม

2
ที่น่าสนใจก็คือไฟล์ (1) เองก็ไม่รวม 0x7f จากการพิจารณาเช่นกันดังนั้นในทางเทคนิคคุณควรใช้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/ หยด / …
Martijn Pieters

@MartijnPieters: ขอบคุณครับ. ฉันได้อัปเดตคำตอบเพื่อยกเว้น0x7f( DEL)
jfs

1
วิธีแก้ปัญหาที่ดีโดยใช้ชุด :-)
Martijn Pieters

ทำไมคุณถึงยกเว้น11หรือVT? ในตารางที่ 11 ถือเป็นข้อความ ASCII ธรรมดาและนี่คือไฟล์vertical tab.
darksky

15

หากคุณใช้ python3 กับ utf-8 มันตรงไปตรงมาเพียงเปิดไฟล์ในโหมดข้อความและหยุดการประมวลผลหากคุณได้รับUnicodeDecodeErrorไฟล์. Python3 จะใช้ Unicode เมื่อจัดการไฟล์ในโหมดข้อความ (และ ByteArray ในโหมด binary) - UnicodeDecodeErrorถ้าการเข้ารหัสของคุณไม่สามารถถอดรหัสไฟล์โดยพลการก็ค่อนข้างมีโอกาสที่คุณจะได้รับ

ตัวอย่าง:

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

ทำไมไม่ใช้with open(filename, 'r', encoding='utf-8') as fโดยตรง?
Terry

8

ถ้ามันช่วยได้ไบนารี่หลายประเภทเริ่มต้นด้วยตัวเลขมหัศจรรย์ นี่คือรายการลายเซ็นของไฟล์


นั่นคือสิ่งที่ libmagic มีไว้สำหรับ ซึ่งสามารถเข้าถึงได้ผ่านทางในหลามหลามมายากล
Bengt

2
น่าเสียดายที่ "ไม่ได้ขึ้นต้นด้วยหมายเลขวิเศษที่รู้จัก" ไม่เทียบเท่ากับ "เป็นไฟล์ข้อความ"
Purrell

8

ลองสิ่งนี้:

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
-1 กำหนด "ไบนารี" ว่ามีศูนย์ไบต์ จะจัดประเภทไฟล์ข้อความที่เข้ารหัส UTF-16 เป็น "ไบนารี"
John Machin

5
@ John Machin: ที่น่าสนใจคือgit diffใช้งานได้จริงและแน่นอนว่ามันตรวจพบไฟล์ UTF-16 เป็นไบนารี
สังหรณ์ใจ

Hunh .. GNU diffก็ทำงานในลักษณะนี้เช่นกัน มีปัญหาคล้ายกันกับไฟล์ UTF-16 fileตรวจพบไฟล์เดียวกันกับข้อความ UTF-16 อย่างถูกต้อง ฉันไม่ได้เช็คเอาต์grepรหัส แต่ตรวจพบไฟล์ UTF-16 เป็นไบนารีด้วย
สังหรณ์ใจ

1
+1 @ John Machin: utf-16 เป็นข้อมูลอักขระตามfile(1)ที่ไม่ปลอดภัยที่จะพิมพ์โดยไม่มีการแปลงดังนั้นวิธีนี้จึงเหมาะสมในกรณีนี้
jfs

2
-1 - ฉันไม่คิดว่า 'มีศูนย์ไบต์' เป็นการทดสอบที่เพียงพอสำหรับไบนารีเทียบกับข้อความตัวอย่างเช่นฉันสามารถสร้างไฟล์ที่มี 0x01 ไบต์ทั้งหมดหรือทำซ้ำ 0xDEADBEEF แต่ไม่ใช่ไฟล์ข้อความ คำตอบตามไฟล์ (1) ดีกว่า
Sam Watkins

6

นี่คือคำแนะนำที่ใช้คำสั่งไฟล์ 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') อ่าน ()
'\ 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คำสั่งที่นั่น) และต้องสร้างกระบวนการภายนอกสำหรับแต่ละไฟล์ซึ่งอาจไม่ถูกปาก


สิ่งนี้ทำให้สคริปต์ของฉันแย่ลง :( จากการตรวจสอบฉันพบว่ามีการอธิบาย conffiles บางส่วนโดยfileเป็น "Sendmail Frozen configuration - version m" - สังเกตว่าไม่มีสตริง "text" อาจใช้file -i?
melissa_boiko

1
TypeError: ไม่สามารถใช้รูปแบบสตริงบนวัตถุคล้ายไบต์
abg

6

ใช้binaryornot library ( GitHub )

มันง่ายมากและขึ้นอยู่กับรหัสที่พบในคำถาม stackoverflow นี้

คุณสามารถเขียนสิ่งนี้ได้ในโค้ด 2 บรรทัด แต่แพ็คเกจนี้ช่วยให้คุณไม่ต้องเขียนและทดสอบโค้ด 2 บรรทัดเหล่านั้นอย่างละเอียดด้วยไฟล์ประเภทแปลก ๆ ข้ามแพลตฟอร์ม


4

โดยปกติคุณต้องเดา

คุณสามารถดูส่วนขยายเป็นเบาะแสเดียวหากไฟล์มี

คุณยังสามารถจดจำรูปแบบไบนารีและเพิกเฉยต่อสิ่งเหล่านั้นได้

มิฉะนั้นให้ดูสัดส่วนของไบต์ ASCII ที่ไม่สามารถพิมพ์ได้ที่คุณมีและเดาจากสิ่งนั้น

คุณยังสามารถลองถอดรหัสจาก UTF-8 และดูว่าให้ผลลัพธ์ที่สมเหตุสมผลหรือไม่


4

วิธีแก้ปัญหาที่สั้นกว่าพร้อมคำเตือน 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

หมายเหตุ: for line in fileอาจใช้หน่วยความจำไม่ จำกัด จำนวนจนกว่าb'\n'จะพบ
jfs

เป็น @Community: ".read()"ส่งคืน bytestring ที่นี่ซึ่งสามารถทำซ้ำได้ (ให้แต่ละไบต์)
jfs

4

เราสามารถใช้ python เองเพื่อตรวจสอบว่าไฟล์นั้นเป็นไบนารีหรือไม่เพราะมันล้มเหลวหากเราพยายามเปิดไฟล์ไบนารีในโหมดข้อความ

def is_binary(file_name):
    try:
        with open(file_name, 'tr') as check_file:  # try open file in text mode
            check_file.read()
            return False
    except:  # if fail then file is non-text (binary)
        return True

สิ่งนี้ล้มเหลวสำหรับไฟล์ ".avi '(วิดีโอ) จำนวนมาก
Anmol Singh Jaggi


2

นี่คือฟังก์ชั่นที่ตรวจสอบก่อนว่าไฟล์เริ่มต้นด้วย BOM หรือไม่และหากไม่ได้ค้นหาศูนย์ไบต์ภายใน 8192 ไบต์เริ่มต้น:

import codecs


#: BOMs to indicate that a file is a text file even if it contains zero bytes.
_TEXT_BOMS = (
    codecs.BOM_UTF16_BE,
    codecs.BOM_UTF16_LE,
    codecs.BOM_UTF32_BE,
    codecs.BOM_UTF32_LE,
    codecs.BOM_UTF8,
)


def is_binary_file(source_path):
    with open(source_path, 'rb') as source_file:
        initial_bytes = source_file.read(8192)
    return not any(initial_bytes.startswith(bom) for bom in _TEXT_BOMS) \
           and b'\0' in initial_bytes

ในทางเทคนิคการตรวจสอบ UTF-8 BOM นั้นไม่จำเป็นเนื่องจากไม่ควรมีศูนย์ไบต์สำหรับวัตถุประสงค์ในทางปฏิบัติทั้งหมด แต่เนื่องจากเป็นการเข้ารหัสทั่วไปจึงตรวจสอบ BOM ได้เร็วกว่าในตอนเริ่มต้นแทนที่จะสแกน 8192 ไบต์ทั้งหมดเป็น 0


2

ลองใช้python-magicที่ดูแลอยู่ในปัจจุบันซึ่งไม่ใช่โมดูลเดียวกันในคำตอบของ @Kami Kisiel สิ่งนี้รองรับทุกแพลตฟอร์มรวมถึง Windows แต่คุณจะต้องใช้ไฟล์libmagicไฟล์ไบนารี สิ่งนี้ได้อธิบายไว้ใน README

ไม่เหมือนกับโมดูลmimetypesคือไม่ใช้นามสกุลของไฟล์และจะตรวจสอบเนื้อหาของไฟล์แทน

>>> import magic
>>> magic.from_file("testdata/test.pdf", mime=True)
'application/pdf'
>>> magic.from_file("testdata/test.pdf")
'PDF document, version 1.2'
>>> magic.from_buffer(open("testdata/test.pdf").read(1024))
'PDF document, version 1.2'

1

ฉันมาที่นี่เพื่อค้นหาสิ่งเดียวกัน - โซลูชันที่ครอบคลุมโดยไลบรารีมาตรฐานเพื่อตรวจจับไบนารีหรือข้อความ หลังจากตรวจสอบตัวเลือกที่คนแนะนำคำสั่งไฟล์ nix ดูเหมือนจะเป็นตัวเลือกที่ดีที่สุด (ฉันกำลังพัฒนาสำหรับ linux boxen เท่านั้น) คนอื่น ๆ บางคนโพสต์วิธีแก้ปัญหาโดยใช้ไฟล์แต่มีความซับซ้อนโดยไม่จำเป็นในความคิดของฉันดังนั้นนี่คือสิ่งที่ฉันคิดขึ้น:

def test_file_isbinary(filename):
    cmd = shlex.split("file -b -e soft '{}'".format(filename))
    if subprocess.check_output(cmd)[:4] in {'ASCI', 'UTF-'}:
        return False
    return True

ควรไปโดยไม่บอก แต่โค้ดของคุณที่เรียกใช้ฟังก์ชันนี้ควรตรวจสอบให้แน่ใจว่าคุณสามารถอ่านไฟล์ได้ก่อนที่จะทำการทดสอบมิฉะนั้นจะตรวจพบไฟล์โดยไม่ถูกต้องว่าเป็นไบนารี


1

ฉันเดาว่าทางออกที่ดีที่สุดคือใช้ฟังก์ชัน guess_type มีรายการที่มีประเภทจำลองหลายแบบและคุณสามารถรวมประเภทของคุณเองได้ นี่คือสคริปต์ที่ฉันใช้เพื่อแก้ปัญหาของฉัน:

from mimetypes import guess_type
from mimetypes import add_type

def __init__(self):
        self.__addMimeTypes()

def __addMimeTypes(self):
        add_type("text/plain",".properties")

def __listDir(self,path):
        try:
            return listdir(path)
        except IOError:
            print ("The directory {0} could not be accessed".format(path))

def getTextFiles(self, path):
        asciiFiles = []
        for files in self.__listDir(path):
            if guess_type(files)[0].split("/")[0] == "text":
                asciiFiles.append(files)
        try:
            return asciiFiles
        except NameError:
            print ("No text files in directory: {0}".format(path))
        finally:
            del asciiFiles

มันอยู่ในชั้นเรียนอย่างที่คุณเห็นตามโครงสร้างของรหัส แต่คุณสามารถเปลี่ยนแปลงสิ่งต่างๆที่คุณต้องการนำไปใช้ในแอปพลิเคชันของคุณได้ มันค่อนข้างง่ายที่จะใช้ เมธอด getTextFiles ส่งคืนอ็อบเจ็กต์รายการพร้อมไฟล์ข้อความทั้งหมดที่อยู่บนไดเร็กทอรีที่คุณส่งผ่านตัวแปรพา ธ


1

บน * NIX:

หากคุณสามารถเข้าถึงfileคำสั่งเชลล์ shlex สามารถช่วยให้โมดูลกระบวนการย่อยใช้งานได้มากขึ้น:

from os.path import realpath
from subprocess import check_output
from shlex import split

filepath = realpath('rel/or/abs/path/to/file')
assert 'ascii' in check_output(split('file {}'.format(filepth).lower()))

หรือคุณสามารถติดมันใน for-loop เพื่อรับเอาต์พุตสำหรับไฟล์ทั้งหมดใน dir ปัจจุบันโดยใช้:

import os
for afile in [x for x in os.listdir('.') if os.path.isfile(x)]:
    assert 'ascii' in check_output(split('file {}'.format(afile).lower()))

หรือสำหรับ subdirs ทั้งหมด:

for curdir, filelist in zip(os.walk('.')[0], os.walk('.')[2]):
     for afile in filelist:
         assert 'ascii' in check_output(split('file {}'.format(afile).lower()))

1

โปรแกรมส่วนใหญ่จะพิจารณาว่าไฟล์เป็นไบนารี (ซึ่งเป็นไฟล์ใด ๆ ที่ไม่ใช่ "line-oriented") หากมีอักขระ NULLตัวละครที่เป็นโมฆะ

นี่คือเวอร์ชันpp_fttext()( pp_sys.c) ของ perl ที่ใช้งานใน Python:

import sys
PY3 = sys.version_info[0] == 3

# A function that takes an integer in the 8-bit range and returns
# a single-character byte object in py3 / a single-character string
# in py2.
#
int2byte = (lambda x: bytes((x,))) if PY3 else chr

_text_characters = (
        b''.join(int2byte(i) for i in range(32, 127)) +
        b'\n\r\t\f\b')

def istextfile(fileobj, blocksize=512):
    """ Uses heuristics to guess whether the given file is text or binary,
        by reading a single block of bytes from the file.
        If more than 30% of the chars in the block are non-text, or there
        are NUL ('\x00') bytes in the block, assume this is a binary file.
    """
    block = fileobj.read(blocksize)
    if b'\x00' in block:
        # Files with null bytes are binary
        return False
    elif not block:
        # An empty file is considered a valid text file
        return True

    # Use translate's 'deletechars' argument to efficiently remove all
    # occurrences of _text_characters from the block
    nontext = block.translate(None, _text_characters)
    return float(len(nontext)) / len(block) <= 0.30

โปรดทราบว่าโค้ดนี้เขียนขึ้นเพื่อให้ทำงานบนทั้ง Python 2 และ Python 3 โดยไม่มีการเปลี่ยนแปลง

ที่มา: "เดาว่าไฟล์เป็นข้อความหรือไบนารี" ของ Perl ถูกนำไปใช้ใน Python


0

คุณอยู่ใน Unix หรือเปล่า ถ้าเป็นเช่นนั้นลอง:

isBinary = os.system("file -b" + name + " | grep text > /dev/null")

ค่าการส่งคืนเชลล์จะกลับด้าน (0 ก็ใช้ได้ดังนั้นหากพบ "ข้อความ" ก็จะส่งกลับเป็น 0 และใน Python นั้นเป็นนิพจน์เท็จ)


สำหรับการอ้างอิงคำสั่ง file จะคาดเดาประเภทตามเนื้อหาของไฟล์ ฉันไม่แน่ใจว่ามันให้ความสำคัญกับนามสกุลไฟล์หรือไม่
David Z

ฉันเกือบจะแน่ใจว่ามันดูทั้งในเนื้อหาและส่วนขยาย
fortran

สิ่งนี้จะแตกหากเส้นทางมี "ข้อความ" ตรวจสอบให้แน่ใจว่าได้ rsplit ที่สุดท้าย ':' (หากไม่มีเครื่องหมายจุดคู่ในคำอธิบายประเภทไฟล์)
Alan Plum

3
ใช้fileกับ-bสวิตช์; มันจะพิมพ์เฉพาะประเภทไฟล์โดยไม่มีเส้นทาง
dubek

2
รุ่นที่ดีกว่าเล็กน้อย:is_binary_file = lambda filename: "text" in subprocess.check_output(["file", "-b", filename])
jfs

0

วิธีที่ง่ายกว่าคือตรวจสอบว่าไฟล์มีอักขระ NULL ( \x00) หรือไม่โดยใช้inตัวดำเนินการเช่น:

b'\x00' in open("foo.bar", 'rb').read()

ดูตัวอย่างทั้งหมดด้านล่าง:

#!/usr/bin/env python3
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('file', nargs=1)
    args = parser.parse_args()
    with open(args.file[0], 'rb') as f:
        if b'\x00' in f.read():
            print('The file is binary!')
        else:
            print('The file is not binary!')

ตัวอย่างการใช้งาน:

$ ./is_binary.py /etc/hosts
The file is not binary!
$ ./is_binary.py `which which`
The file is binary!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.