2009-09-18 41 views
13

Tôi cần xác định xem tệp nào tệpnhị phân và văn bản trong một thư mục.Làm cách nào để xác định tệp nhị phân và tệp văn bản bằng Python?

Tôi đã thử sử dụng mimetypes nhưng không phải là ý tưởng hay trong trường hợp của tôi vì nó không thể xác định tất cả các tệp, và tôi có người lạ ở đây ... Tôi chỉ cần biết, nhị phân hoặc văn bản. Đơn giản ? Nhưng tôi couldn't tìm một giải pháp ...

Cảm ơn

+2

Tệp văn bản cho bạn là gì? Ví dụ, mã UTF-16-BE được mã hóa Unicode? –

+3

Bạn cần phải xác định chính xác những gì có nghĩa là 'nhị phân' và 'văn bản' trước khi bất cứ ai có thể giúp bạn. –

+0

Tệp văn bản là bất kỳ tệp nào có thể đọc được bởi con người. Giả sử, bất kỳ tệp nào bạn có thể đọc bằng lệnh "mèo" (linux) hoặc "loại" (cửa sổ). – Thomas

Trả lời

9

Cảm ơn tất cả mọi người, tôi tìm thấy một giải pháp phù hợp với vấn đề của tôi. Tôi tìm thấy mã này tại http://code.activestate.com/recipes/173220/ và tôi đã thay đổi một chút để phù hợp với tôi.

Nó hoạt động tốt.

from __future__ import division 
import string 

def istext(filename): 
    s=open(filename).read(512) 
    text_characters = "".join(map(chr, range(32, 127)) + list("\n\r\t\b")) 
    _null_trans = string.maketrans("", "") 
    if not s: 
     # Empty files are considered text 
     return True 
    if "\0" in s: 
     # Files with null bytes are likely binary 
     return False 
    # Get the non-text characters (maps a character to itself then 
    # use the 'remove' option to get rid of the text characters.) 
    t = s.translate(_null_trans, text_characters) 
    # If more than 30% non-text characters, then 
    # this is considered a binary file 
    if float(len(t))/float(len(s)) > 0.30: 
     return False 
    return True 
+7

Một chút sửa đổi cho mã của bạn: 'nếu float (len (t))/float (len)> 0,30: return 0' Nếu không, python sẽ sử dụng phân chia số nguyên và so sánh sẽ chỉ đúng khi len (t) == len (s) –

+1

Thomas, hãy áp dụng điều chỉnh "nổi" đó cho câu trả lời! Activestate cũng nên sửa công thức của họ! ;) nhưng tôi không thể bị làm phiền khi đăng ký để đưa ra các bình luận ở đó. –

+0

cũng có dấu * ở dòng cuối cùng, không nên ở đó –

4

Nếu kịch bản của bạn đang chạy trên * nix, bạn có thể sử dụng một cái gì đó như thế này:

import subprocess 
import re 

def is_text(fn): 
    msg = subprocess.Popen(["file", fn], stdout=subprocess.PIPE).communicate()[0] 
    return re.search('text', msg) != None 
+0

Không cần phải «re' nếu chỉ tìm chuỗi con. –

+0

Không hoạt động nếu 'văn bản' là một phần của tệp nhị phân tệp nhị phân. – Paddre

+1

Tôi đề xuất Popen (["tệp", "--mime", fn]. ...). Nếu không, từ "văn bản" có thể không xuất hiện. Trên Linux của tôi, câu trả lời cho một cái gì đó trông giống như một chương trình Fortran là "chương trình FORTAN". Nếu bạn thêm công tắc mime, bạn sẽ nhận được "text/x-fortran; charset = us-ascii". – Tsf

7

Đó là vốn không đơn giản. Không có cách nào để biết chắc chắn, mặc dù bạn có thể đoán một cách hợp lý trong hầu hết các trường hợp.

Những điều bạn có thể muốn làm:

  • Hãy tìm con số ma thuật được biết đến trong chữ ký nhị phân
  • Look cho Unicode byte-trật tự-mark vào lúc bắt đầu của tập tin
  • Nếu tập tin là thường xuyên 00 xx 00 xx 00 xx (đối với xx tùy ý) hoặc ngược lại, có thể là UTF-16
  • Nếu không, hãy tìm số 0 trong tệp; tệp có số 0 ở là không thể là tệp văn bản mã hóa một byte.

Nhưng đó là tất cả heuristic - có thể có một tệp có tệp văn bản hợp lệ một tệp hình ảnh hợp lệ chẳng hạn. Nó có thể là vô nghĩa như một tập tin văn bản, nhưng hợp pháp trong một số mã hóa hoặc khác ...

4

Nó có thể là có thể sử dụng libmagic đoán kiểu MIME của tập tin sử dụng python-magic. Nếu bạn lấy lại nội dung nào đó trong không gian tên "text/*", đó có thể là tệp văn bản, trong khi bất kỳ điều gì khác có thể là binary file.

Các vấn đề liên quan