在Python中搜索/读取二进制数据
我正在读取一个二进制文件(这个例子是一个jpg图片),需要在这个文件中找到一些值。如果你感兴趣的话,这个二进制文件是一个jpg,我想通过查看它的二进制结构来提取它的尺寸,具体可以参考这里的详细说明。
我需要在二进制数据中找到FFC0,跳过一些字节,然后读取4个字节(这样我就能得到图片的尺寸)。
在二进制数据中搜索这个值有什么好的方法吗?有没有类似于'find'的功能,或者像re这样的东西?
8 个回答
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))
与其把整个文件都读到内存里,然后再去搜索,最后再写一个新文件到磁盘上,不如使用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')
你可以把文件加载到一个字符串里,然后用这个字符串去查找字节序列 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'\xff\xc0'
前面加上 b
都无所谓。而且如果你的平台对待二进制文件和文本文件是一样的(比如 Mac 或 Linux),那么使用 'r'
或 'rb'
作为文件模式也没有区别。不过我还是建议使用上面第一个代码示例那样的写法,以便将来兼容——如果你以后换到 Python 3,这样就少了一件需要修改的事情。