在Python中搜索/读取二进制数据

时间:2010-07-10 00:39:41

标签: python search binary

我正在读取二进制文件(在这种情况下为jpg),并且需要在该文件中找到一些值。对于那些感兴趣的人,二进制文件是一个jpg,我试图通过查找二进制结构detailed here来挑选它的维度。

我需要在二进制数据中找到FFC0,跳过一些字节数,然后读取4个字节(这应该给我图像尺寸)。

在二进制数据中搜索值的好方法是什么?是否有相当于'find'或类似re?

的东西

8 个答案:

答案 0 :(得分:11)

您实际上可以将文件加载到字符串中,并使用0xffc0方法搜索该字符串str.find()的字符串。它适用于任何字节序列。

执行此操作的代码取决于几个方面。如果你以二进制模式打开文件而你正在使用Python 3(这两者都可能是这种情况的最佳实践),你需要搜索一个字节串(而不是字符串),这意味着你必须在字符串前加b

with open(filename, 'rb') as f:
    s = f.read()
s.find(b'\xff\xc0')

如果在Python 3中以文本模式打开文件,则必须搜索字符串:

with open(filename, 'r') as f:
    s = f.read()
s.find('\xff\xc0')

虽然没有特别的理由这样做。它不会比以前的方式有任何优势,如果你在一个平台上以不同的方式处理二进制文件和文本文件(例如Windows),那么这可能会导致问题。

Python 2没有对字节字符串和字符串进行区分,因此如果您使用的是该版本,则在b中包含或排除b'\xff\xc0'无关紧要。如果您的平台以相同方式处理二进制文件和文本文件(例如Mac或Linux),那么使用'r''rb'作为文件模式也无关紧要。但是我仍然建议使用上面第一个代码示例之类的东西,只是为了向前兼容 - 如果你切换到Python 3,那么修复它就少了一点。

答案 1 :(得分:6)

bitstring模块的设计目的非常重要。对于您的情况,以下代码(我尚未测试过)应该有助于说明:

from bitstring import ConstBitStream
# Can initialise from files, bytes, etc.
s = ConstBitStream(filename='your_file')
# Search to Start of Frame 0 code on byte boundary
found = s.find('0xffc0', bytealigned=True)
if found:
    print("Found start code at byte offset %d." % found[0])
    s0f0, length, bitdepth, height, width = s.readlist('hex:16, uint:16, 
                                                        uint:8, 2*uint:16')
    print("Width %d, Height %d" % (width, height))

答案 2 :(得分:5)

不是将整个文件读入内存,搜索它然后将新文件写入磁盘,而是可以使用mmap模块。 mmap将将整个文件存储在内存中,并允许进行就地修改。

#!/usr/bin/python

import mmap

with open("hugefile", "rw+b") as f:
    mm = mmap.mmap(f.fileno(), 0)
    print mm.find('\x00\x09\x03\x03')

答案 3 :(得分:4)

re模块支持同时使用字符串和二进制数据(Python 2中的str和Python 3中的bytes ),所以你可以使用它和str.find来完成任务。

答案 4 :(得分:2)

嗯,显然有PIL Image模块的大小是一个属性。如果您想要获得建议的大小,并且没有加载文件,您将不得不逐行浏览。不是最好的方法,但它会起作用。

答案 5 :(得分:1)

只有在您需要知道sub的位置时才应使用find()方法,否则,您可以使用in运算符,例如:

with open("foo.bin", 'rb') as f:
    if b'\x00' in f.read():
        print('The file is binary!')
    else:
        print('The file is not binary!')

答案 6 :(得分:1)

在Python 3.x中,您可以通过另一个字节字符串搜索字节字符串,如下所示:

>>> byte_array = b'this is a byte array\r\n\r\nXYZ\x80\x04\x95 \x00\x00\x00\x00\x00'
>>> byte_array.find('\r\n\r\n'.encode())
20
>>>

答案 7 :(得分:0)

对于Python> = 3.2:

import re

f = open("filename.jpg", "rb")
byte = f.read()
f.close()

matchObj = re.match( b'\xff\xd8.*\xff\xc0...(..)(..).*\xff\xd9', byte, re.MULTILINE|re.DOTALL)
if matchObj:
    # http://stackoverflow.com/questions/444591/convert-a-string-of-bytes-into-an-int-python
    print (int.from_bytes(matchObj.group(1), 'big')) # height
    print (int.from_bytes(matchObj.group(2), 'big')) # width