如何在Python中确定流是文本还是二进制?

时间:2014-04-09 06:23:34

标签: python text text-files classification binaryfiles

有没有办法确定(测试,检查或分类)文件(或字节流,或其他类文件对象)是文本还是二进制,在大多数情况下,类似于Unix中file命令的魔力?

动机:虽然{<3}},Python 可以决定这一点,但我想利用这项功能。可以覆盖有用数量的案例并处理例外情况。

优先考虑跨平台或纯python方法。一种方法是guesswork should be avoided但是它依赖于Windows上的Cygwin和一般的 libmagic

1 个答案:

答案 0 :(得分:1)

来自file手册页:

  

打印的类型通常包含一个单词text(文件   仅包含打印字符和一些        常见的控制字符,并且可以安全地在ASCII终端上读取),可执行文件(该文件包含        以某种UNIX内核或其他内容可理解的形式编译程序的结果,或者数据意味着什么        else(数据通常是“二进制”或不可打印的。)

看到你只是想确定它是文本还是二进制文件,我只想检查流中的每个字符是否都是可打印的

import string
all(c in string.printable for c in stream)

我认为你不可能100%正确,但这应该是相当准确的。你需要处理unicode编码吗?

编辑 - Unicode支持有点棘手,但如果您有一组可能的编码,那么您可以在检查所有字符是否可打印之前测试文档是否从每个编码成功解码

import string
import unicodedata

encodings = 'ascii', 'utf-8', 'utf-16'

test_strings = '\xf0\x01\x01\x00\x44', 'this is a test', 'a utf-8 test \xe2\x98\x83'

def attempt_decode(s, encodings):
    for enc in encodings:
        try:
            return s.decode(enc), enc
        except UnicodeDecodeError:
            pass
    return s, 'binary'

def printable(s):
    if isinstance(s, unicode):
        return not any(unicodedata.category(c) in ['Cc'] for c in s)
    return all(c in string.printable for c in s)

for s in test_strings:
    result, enc = attempt_decode(s, encodings)
    if enc != 'binary':
        if not printable(result):
            result, enc = s, 'binary'
    print enc + ' - ' + repr(result)

这导致:

binary - '\xf0\x01\x01\x00D'
ascii - u'this is a test'
utf-8 - u'a utf-8 test \u2603'
相关问题