我正在阅读一个二进制文件(在这种情况下是jpg格式),需要在其中找到一些值。对于那些感兴趣的人,这个二进制文件是一个jpg文件,我正在尝试通过查找二进制结构来获取其尺寸,如详细介绍所述。
我需要在二进制数据中找到FFC0,然后跳过一定字节数,接着读取4个字节(这应该给我图像的尺寸)。
有没有好的方法搜索二进制数据中的值?是否有类似于“find”或re的功能?
我正在阅读一个二进制文件(在这种情况下是jpg格式),需要在其中找到一些值。对于那些感兴趣的人,这个二进制文件是一个jpg文件,我正在尝试通过查找二进制结构来获取其尺寸,如详细介绍所述。
我需要在二进制数据中找到FFC0,然后跳过一定字节数,接着读取4个字节(这应该给我图像的尺寸)。
有没有好的方法搜索二进制数据中的值?是否有类似于“find”或re的功能?
str.find()
方法查找该字符串中的字节序列0xffc0
。它适用于任何字节序列。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),这可能会导致问题。b
,都没有关系。而且如果您的平台将二进制文件和文本文件视为相同(例如Mac或Linux),那么使用'r'
或'rb'
作为文件模式也无关紧要。但我仍然建议像以上第一个代码示例一样去编写,以便实现向前兼容-以防你将来切换到Python 3,就少了一件事需要修复。使用 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')
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))
Bits.find
只返回一个布尔值并设置 Bits.bytepos
属性?也许在模块文档中,您应该警告 bitstring
不是线程安全的(当然,在这个答案中并不重要)。 - tzotfind
可以返回一个包含所有必要信息的对象,就像 re.match
和 re.search
一样。你可以将这个“BitMatch”类作为 bool
的子类,以保持向后兼容性。 - tzot>>> 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
>>>
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!')
对于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:
# https://dev59.com/J3RB5IYBdhLWcg3w-8Lo
print (int.from_bytes(matchObj.group(1), 'big')) # height
print (int.from_bytes(matchObj.group(2), 'big')) # width