将Hex字符串文件转换为整数的最佳方法

时间:2015-10-08 20:01:08

标签: python python-2.7 cython binaryfiles

我在二进制文件中有10GB的数据,只有很少的endian格式,我将它们转换为整数,如:

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的数据转换每个文件需要很长时间。有没有办法加快这个过程?

3 个答案:

答案 0 :(得分:4)

如果您不介意使用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)

答案 1 :(得分:4)

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)

答案 2 :(得分:0)

根据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])

有关标准库

mmap模块的详细信息,请阅读here