Python 将二进制文件读入结构
我有一个已知格式/结构的二进制文件 如何将所有二进制数据读入结构的数组中 类似(在伪代码中) 编辑: 迄今为止的解决办法:Python 将二进制文件读入结构,python,binaryfiles,Python,Binaryfiles,我有一个已知格式/结构的二进制文件 如何将所有二进制数据读入结构的数组中 类似(在伪代码中) 编辑: 迄今为止的解决办法: data = [] fmt = '=iiiii256i' fmt_s = '=iiiii' fmt_spec = '256i' struct_size = struct.calcsize(fmt) for i in range(struct_size, len(bytes)-struct_size, struct_size): dat1= list(str
data = []
fmt = '=iiiii256i'
fmt_s = '=iiiii'
fmt_spec = '256i'
struct_size = struct.calcsize(fmt)
for i in range(struct_size, len(bytes)-struct_size, struct_size):
dat1= list(struct.unpack(fmt_s, bytes[i-struct_size:i-1024]))
dat2= list(struct.unpack(fmt_spec, bytes[i-1024:i]))
dat1.append(dat2)
data.append(dat1)
使用;您需要以该库中记录的字符串格式定义类型:
struct.unpack('=HHf255s', bytes)
上面的示例需要本机字节顺序、两个无符号短字符、一个浮点和255个字符的字符串
要循环一个已经完全读取的字节
字符串,我将使用itertools
;我在这里采用了一个方便的方法:
from itertools import izip_longest, imap
from struct import unpack, calcsize
fmt_s = '=5i'
fmt_spec = '=256i'
size_s = calcsize(fmt_s)
size = size_s + calcsize(fmt_spec)
def chunked(iterable, n, fillvalue=''):
args = [iter(iterable)] * n
return imap(''.join, izip_longest(*args, fillvalue=fillvalue))
data = [unpack(fmt_s, section[:size_s]) + (unpack(fmt_spec, section[size_s:]),)
for section in chunked(bytes, size)]
这将生成元组而不是列表,但如果必须执行以下操作,则可以很容易地进行调整:
data = [list(unpack(fmt_s, section[:size_s])) + [list(unpack(fmt_spec, section[size_s:]))]
for section in chunked(bytes, size)]
添加评论
import struct
首先,将二进制文件读入数组
mbr = file('mbrcontent', 'rb').read()
所以你们可以从数组中取出一些片段
partition_table = mbr[446:510]
然后将其解包为整数
signature = struct.unpack('<H', mbr[510:512])[0]
signature=struct.unpack(“实际上,看起来您正在尝试读取列表(或数组)在Python中执行此操作的惯用方法是使用struct
模块并在循环中调用固定次数(如果您事先知道它们的数量),或者直到到达文件末尾并将结果存储在列表中。下面是后者的一个示例:
import struct
struct_fmt = '=5if255s' # int[5], float, byte[255]
struct_len = struct.calcsize(struct_fmt)
struct_unpack = struct.Struct(struct_fmt).unpack_from
results = []
with open(filename, "rb") as f:
while True:
data = f.read(struct_len)
if not data: break
s = struct_unpack(data)
results.append(s)
同样的结果也可以使用一个简短的助手(即下面的read_chunks()
)更简洁地获得:
更新
事实上,您不需要如上所示显式定义助手函数,因为您可以使用Python的内置函数在列表中动态创建所需的对象,如下所示:
from functools import partial
with open(filename, "rb") as f:
results = [struct_unpack(chunk) for chunk in iter(partial(f.read, struct_len), b'')]
导入操作系统,重新
导入功能工具
导入ctypes
从ctypes导入字符串、byref、sizeof、cast、指针、指针、创建字符串缓冲区、memmove
将numpy作为np导入
作为pd进口熊猫
类_StructBase(ctypes.Structure):
__类型=0
_字段\=[]
@类方法
def偏移量(cls,字段):
模式='(?P\w+)\[(?P\d+)\]
mat=重新匹配(模式、字段)
如有必要:
fields=dict(cls.fields())
f=mat.groupdict()['field']
idx=mat.groupdict()['idx']
返回cls.Offsetof(f)+int(idx)*ctypes.sizeof(字段[字段])
其他:
返回getattr(cls,字段).offset
@类方法
def数据类型(cls):
地图={
ctypes.c_字节:np.byte,
ctypes.c_ubyte:np.ubyte,
ctypes.c_char:np.ubyte,
ctypes.c_int8:np.int8,
c类型c_int16:np.int16,
ctypes.c_int32:np.int32,
ctypes.c_int64:np.int64,
c类型c_uint8:np.uint8,
ctypes.c_uint16:np.uint16,
c类型c_uint32:np.uint32,
c类型c_uint64:np.uint64,
ctypes.c_float:np.float32,
ctypes.c_double:np.64,
}
res=[]
对于cls.Fields()中的k,v:
如果hasattr(v,'u长度'):
如果v._type.=ctypes.c_char:
对于范围内的i(v.。_长度):
res.append((k,map[v],cls.Offsetof(k)))
其他:
res.append((k,'S%d'%v.\u长度,cls.Offsetof(k)))
其他:
res.append((k,map[v],cls.Offsetof(k)))
res=pd.DataFrame(res,columns=['name','format','offset'])
返回np.dtype({
“名称”:res[“名称”],
“格式”:res[“格式”],
“偏移量”:res[“偏移量”],
})
@类方法
def属性(cls):
字段=cls.\u字段_
res=[]
对于attr,字段中的tp:
如果str(tp).find(''u数组'')>0和str(tp).find('char\u数组'')<0:
对于范围内的i(tp.\U长度):
res.append((attr+'[%s]'%str(i),tp.\u类型)
其他:
res.append((attr,tp))
返回res
@类方法
def字段(cls,notype=False):
res=[cls.Attr()]
cur_cls=cls
尽管如此:
cur_cls=cur_cls.\uuuuuu base\uuuuuuu[0]
如果cur_cls==ctypes.Structure:
打破
res.append(cur_cls.Attr())
如果不输入:
返回[k代表k,v在functools.reduce(list.\uu添加\uuuu,反转(res),[])]
其他:
return functools.reduce(list.\uuuu add\uuuuu,reversed(res),[]))
@类方法
def大小(cls):
返回大小(cls)
@类方法
来自结构二进制文件的定义(cls,路径,最大计数=2**32,解码=True):
打印(os.path.getsize(path),cls.size())
断言os.path.getsize(路径)%cls.size()==0
size=os.path.getsize(path)//cls.size()
尺寸=最小值(尺寸,最大计数)
索引=范围(大小)
array=np.fromfile(路径,dtype=cls.dtype(),count=size)
df=pd.DataFrame(数组,index=index)
对于attr,评估中的tp(str(cls.DType()):
如果re.match('S\d+',tp)不是None并解码:
尝试:
df[attr]=df[attr].map(lambda x:x.decode(“utf-8”))
除:
df[attr]=df[attr].map(lambda x:x.decode(“gbk”))
返回df
类StructBase(_StructBase):
_字段=[
(“类型”,ctypes.c_uint32),
]
类索引结构(StructBase):
_字段=[
('Seq',ctypes.c_uint32),
('ExID',ctypes.c_char*8),
(“SecID”,ctypes.c_char*8),
(“SecName”,ctypes.c_char*16),
('SourceID',ctypes.c_int32),
(“时间”,ctypes.c_uint32),
('PreClose',ctypes.c_uint32),
(“开放”,ctypes.c_uint32),
(“高”,ctypes.c_uint32),
(“低”,ctypes.c_uint32),
(“匹配”,ctypes.c_uint32),
]
df=IndexStruct.from_struct_binary('您的路径')
打印(df)
-1:请修复缩进并解释此代码演示的内容。这似乎不适用于大于结构大小的数据。我的二进制数据会自动重复。@lejon:它不会从中删除读取的数据
import struct
struct_fmt = '=5if255s' # int[5], float, byte[255]
struct_len = struct.calcsize(struct_fmt)
struct_unpack = struct.Struct(struct_fmt).unpack_from
results = []
with open(filename, "rb") as f:
while True:
data = f.read(struct_len)
if not data: break
s = struct_unpack(data)
results.append(s)
def read_chunks(f, length):
while True:
data = f.read(length)
if not data: break
yield data
with open(filename, "rb") as f:
results = [struct_unpack(chunk) for chunk in read_chunks(f, struct_len)]
from functools import partial
with open(filename, "rb") as f:
results = [struct_unpack(chunk) for chunk in iter(partial(f.read, struct_len), b'')]