Python 使用memoryview读取二进制文件
我阅读了下面代码中的一个大文件,它有一个特殊的结构,其中包括两个需要同时处理的块。我没有在文件中来回搜索,而是加载了包装在Python 使用memoryview读取二进制文件,python,python-2.7,binaryfiles,memoryview,Python,Python 2.7,Binaryfiles,Memoryview,我阅读了下面代码中的一个大文件,它有一个特殊的结构,其中包括两个需要同时处理的块。我没有在文件中来回搜索,而是加载了包装在memoryview调用中的这两个块 with open(abs_path, 'rb') as bsa_file: # ... # load the file record block to parse later file_records_block = memoryview(bsa_file.read(file_records_block_size
memoryview
调用中的这两个块
with open(abs_path, 'rb') as bsa_file:
# ...
# load the file record block to parse later
file_records_block = memoryview(bsa_file.read(file_records_block_size))
# load the file names block
file_names_block = memoryview(bsa_file.read(total_file_name_length))
# close the file
file_records_index = names_record_index = 0
for folder_record in folder_records:
name_size = struct.unpack_from('B', file_records_block, file_records_index)[0]
# discard null terminator below
folder_path = struct.unpack_from('%ds' % (name_size - 1),
file_records_block, file_records_index + 1)[0]
file_records_index += name_size + 1
for __ in xrange(folder_record.files_count):
file_name_len = 0
for b in file_names_block[names_record_index:]:
if b != '\x00': file_name_len += 1
else: break
file_name = unicode(struct.unpack_from('%ds' % file_name_len,
file_names_block,names_record_index)[0])
names_record_index += file_name_len + 1
该文件已正确解析,但由于这是我第一次使用mamoryview接口,我不确定是否正确。文件名块由以null结尾的c字符串组成
文件\u名称\u块[名称\u记录\u索引:
,还是创建一些n^2个切片?我需要在这里使用islice
cast()
(docs?)——有没有办法用它(或其他技巧)将视图拆分为字节?我可以调用split('\x00')
?这会保持内存效率吗我希望您能深入了解一种正确的方法(在python 2中)。A
memoryview
在处理以空结尾的字符串时不会给您带来任何好处,因为它们除了固定宽度的数据之外没有任何功能。您也可以在此处使用bytes.split()
:
file_names_block = bsa_file.read(total_file_name_length)
file_names = file_names_block.split(b'\00')
切片memoryview
不会使用额外的内存(视图参数除外),但如果使用强制转换,则在尝试访问序列中的元素时,会为解析的内存区域生成新的本机对象
您仍然可以使用memoryview
进行文件\记录\块
解析;这些字符串以长度作为前缀,使您有机会使用切片。只需在处理文件夹路径
值时对内存视图的字节进行切片,就无需保留索引:
for folder_record in folder_records:
name_size = file_records_block[0] # first byte is the length, indexing gives the integer
folder_path = file_records_block[1:name_size].tobytes()
file_records_block = file_records_block[name_size + 1:] # skip the null
由于
memoryview
来自bytes
对象,索引将为您提供一个字节的整数值,给定切片上的.tobytes()
为该节提供一个新的bytes
字符串,然后,您可以继续切片,将剩余部分留给下一个循环。我不认为MemoryView在这里给您带来任何东西;内存视图,如struct
模块,对于以空结尾的字符串没有特定的功能。确实谢谢:)我想我可以使用split然后添加del file\u names\u block
。至于我认为应该是的,是不是应该是file\u records\u block[name\u size:][/code>?我想知道在最后一次操作之后(底层缓冲区的)内存被释放的速度有多快,但这是给c组的:)@Mr_和_Mrs_D:你可以在循环后使用文件记录块.release()
来释放字节
对象。@Mr_和_Mrs_D:我不确定你对文件记录块[name\u size:]
不过..oooooo ps-文件记录块[name\u size+1:]抱歉午睡!总之,你认为我的方法能给我带来什么吗?这是读取结构化二进制文件的好方法吗?@Mr_和Mrs_D:啊,当时误解了那里的结构。我认为它们是Pascal字符串(单字节长度前缀,然后字符串值为length-1字节)。然后必须在name\u size+1
处切片下一个块。