将十六进制字符串文件转换为整数的最佳方法
Best way to convert Hex string file to integer
我有 10GB 的小端格式二进制文件数据,我正在将它们转换为整数,例如:
with open(myfile, 'rb') as inh:
data = inh.read()
for i in range(0, len(data), 4):
pos = struct.unpack('i', data[i:i+4])
但是转换每个100MB数据的文件需要很长时间。有什么办法可以加快这个过程吗?
如果你不介意使用numpy,你可以使用numpy.memmap
:
import numpy as np
data = np.memmap('foo.bin', dtype='<i4', mode='r')
例如,
In [122]: !hexdump foo.bin
0000000 01 00 00 00 02 00 00 00 03 00 00 00 ff 00 00 00
0000010 00 01 00 00 01 01 00 00 ff ff ff ff fe ff ff ff
0000020
In [123]: data = np.memmap('foo.bin', dtype='<i4', mode='r')
In [124]: data
Out[124]: memmap([ 1, 2, 3, 255, 256, 257, -1, -2], dtype=int32)
In [125]: data[6]
Out[125]: -1
可能不需要内存映射数据,在这种情况下,您只需使用 numpy.fromfile
将其读入数组即可。例如,
In [129]: data = np.fromfile('foo.bin', dtype='<i4')
In [130]: data
Out[130]: array([ 1, 2, 3, 255, 256, 257, -1, -2], dtype=int32)
numpy
可能更快,但您也可以允许 struct.unpack
执行循环而不是 Python:
L = struct.unpack('{}i'.format(len(data)//4),data)
结果是解包后的整个整数列表。
做一个 400MB 的数据 blob 花了几秒钟。这是一个较短的例子:
>>> L=list(range(20))
>>> struct.pack('20i',*L)
b'\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\r\x00\x00\x00\x0e\x00\x00\x00\x0f\x00\x00\x00\x10\x00\x00\x00\x11\x00\x00\x00\x12\x00\x00\x00\x13\x00\x00\x00'
>>> b = struct.pack('20i',*L)
>>> struct.unpack('20i',b)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
按照 Padraic Cunningham 的建议,使用内存映射文件:
import mmap
import contextlib
with open(myfile, 'rb') as inh:
with contextlib.closing(mmap.mmap(inh.fileno(), 0, access=mmap.ACCESS_READ)) as m:
for i in range(0, len(m), 4):
pos = struct.unpack('i', m[i:i+4])
请阅读 here 以获取有关标准库中 mmap
模块的更多信息
我有 10GB 的小端格式二进制文件数据,我正在将它们转换为整数,例如:
with open(myfile, 'rb') as inh:
data = inh.read()
for i in range(0, len(data), 4):
pos = struct.unpack('i', data[i:i+4])
但是转换每个100MB数据的文件需要很长时间。有什么办法可以加快这个过程吗?
如果你不介意使用numpy,你可以使用numpy.memmap
:
import numpy as np
data = np.memmap('foo.bin', dtype='<i4', mode='r')
例如,
In [122]: !hexdump foo.bin
0000000 01 00 00 00 02 00 00 00 03 00 00 00 ff 00 00 00
0000010 00 01 00 00 01 01 00 00 ff ff ff ff fe ff ff ff
0000020
In [123]: data = np.memmap('foo.bin', dtype='<i4', mode='r')
In [124]: data
Out[124]: memmap([ 1, 2, 3, 255, 256, 257, -1, -2], dtype=int32)
In [125]: data[6]
Out[125]: -1
可能不需要内存映射数据,在这种情况下,您只需使用 numpy.fromfile
将其读入数组即可。例如,
In [129]: data = np.fromfile('foo.bin', dtype='<i4')
In [130]: data
Out[130]: array([ 1, 2, 3, 255, 256, 257, -1, -2], dtype=int32)
numpy
可能更快,但您也可以允许 struct.unpack
执行循环而不是 Python:
L = struct.unpack('{}i'.format(len(data)//4),data)
结果是解包后的整个整数列表。
做一个 400MB 的数据 blob 花了几秒钟。这是一个较短的例子:
>>> L=list(range(20))
>>> struct.pack('20i',*L)
b'\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\r\x00\x00\x00\x0e\x00\x00\x00\x0f\x00\x00\x00\x10\x00\x00\x00\x11\x00\x00\x00\x12\x00\x00\x00\x13\x00\x00\x00'
>>> b = struct.pack('20i',*L)
>>> struct.unpack('20i',b)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
按照 Padraic Cunningham 的建议,使用内存映射文件:
import mmap
import contextlib
with open(myfile, 'rb') as inh:
with contextlib.closing(mmap.mmap(inh.fileno(), 0, access=mmap.ACCESS_READ)) as m:
for i in range(0, len(m), 4):
pos = struct.unpack('i', m[i:i+4])
请阅读 here 以获取有关标准库中 mmap
模块的更多信息