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

Par*_*and 22 python binary search

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

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

在二进制数据中搜索值的好方法是什么?有没有相当于'发现',或类似的东西?

Dav*_*d Z 13

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

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

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

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

with open(filename, 'r') as f:
    s = f.read()
s.find('\xff\xc0')
Run Code Online (Sandbox Code Playgroud)

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

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

  • 如果它是一个非常大的文件,那么将它一次性读入字符串并不是一个好主意. (7认同)
  • 由于我只是在寻找第一帧,我可能会读取文件的一小部分并处理而不是读取整个文件. (3认同)
  • 我怀疑它是如此之大,这将成为一个问题. (2认同)

Sco*_*ths 6

位串模块是专为非常这一目的.对于您的情况,以下代码(我没有测试过)应该有助于说明:

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))
Run Code Online (Sandbox Code Playgroud)


cal*_*leb 6

在 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
>>>
Run Code Online (Sandbox Code Playgroud)


And*_*ikh 5

re模块可以处理字符串和二进制数据(str在 Python 2 和bytesPython 3 中),因此您可以将它用于str.find您的任务。


syn*_*tel 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')
Run Code Online (Sandbox Code Playgroud)