提高读取二进制文件的速度
improve speed when reading a binary file
我有一个大型二进制文件,我想在数组中读取它。
二进制文件的格式为:
- 每行的开头和结尾有一个额外的 4 个字节的数据,我没有使用;
- 中间有 8 个字节值
我是这样做的:
# nlines - number of row in the binary file
# ncols - number of values to read from a row
fidbin=open('toto.mda' ,'rb'); #open this file
temp = fidbin.read(4) #skip the first 4 bytes
nvalues = nlines * ncols # Total number of values
array=np.zeros(nvalues,dtype=np.float)
#read ncols values per line and skip the useless data at the end
for c in range(int(nlines)): #read the nlines of the *.mda file
matrix = np.fromfile(fidbin, np.float64,count=int(ncols)) #read all the values from one row
Indice_start = c*ncols
array[Indice_start:Indice_start+ncols]=matrix
fidbin.seek( fidbin.tell() + 8) #fid.tell() the actual read position + skip bytes (4 at the end of the line + 4 at the beginning of the second line)
fidbin.close()
它运行良好,但问题是对于大型二进制文件来说速度很慢。
有没有办法提高二进制文件的读取速度?
您可以使用结构化数据类型并通过一次调用 numpy.fromfile
来读取文件。例如,我的文件 qaz.mda
在每行开始和结束的四个字节标记之间有五列浮点值。以下是创建结构化数据类型和读取数据的方法。
首先,创建一个与每一行的格式匹配的数据类型:
In [547]: ncols = 5
In [548]: dt = np.dtype([('pre', np.int32), ('data', np.float64, ncols), ('post', np.int32)])
将文件读入结构化数组:
In [549]: a = np.fromfile("qaz.mda", dtype=dt)
In [550]: a
Out[550]:
array([(1, [0.0, 1.0, 2.0, 3.0, 4.0], 0),
(2, [5.0, 6.0, 7.0, 8.0, 9.0], 0),
(3, [10.0, 11.0, 12.0, 13.0, 14.0], 0),
(4, [15.0, 16.0, 17.0, 18.0, 19.0], 0),
(5, [20.0, 21.0, 22.0, 23.0, 24.0], 0)],
dtype=[('pre', '<i4'), ('data', '<f8', (5,)), ('post', '<i4')])
只提取我们想要的数据:
In [551]: data = a['data']
In [552]: data
Out[552]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
您也可以尝试 numpy.memmap
看看它是否提高了性能:
In [563]: a = np.memmap("qaz.mda", dtype=dt)
In [564]: a
Out[564]:
memmap([(1, [0.0, 1.0, 2.0, 3.0, 4.0], 0),
(2, [5.0, 6.0, 7.0, 8.0, 9.0], 0),
(3, [10.0, 11.0, 12.0, 13.0, 14.0], 0),
(4, [15.0, 16.0, 17.0, 18.0, 19.0], 0),
(5, [20.0, 21.0, 22.0, 23.0, 24.0], 0)],
dtype=[('pre', '<i4'), ('data', '<f8', (5,)), ('post', '<i4')])
In [565]: data = a['data']
In [566]: data
Out[566]:
memmap([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
注意上面的data
仍然是一个内存映射数组。为确保数据复制到内存中的数组中,可以使用numpy.copy
:
In [567]: data = np.copy(a['data'])
In [568]: data
Out[568]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
这是否有必要取决于您将如何在其余代码中使用该数组。
我有一个大型二进制文件,我想在数组中读取它。 二进制文件的格式为:
- 每行的开头和结尾有一个额外的 4 个字节的数据,我没有使用;
- 中间有 8 个字节值
我是这样做的:
# nlines - number of row in the binary file
# ncols - number of values to read from a row
fidbin=open('toto.mda' ,'rb'); #open this file
temp = fidbin.read(4) #skip the first 4 bytes
nvalues = nlines * ncols # Total number of values
array=np.zeros(nvalues,dtype=np.float)
#read ncols values per line and skip the useless data at the end
for c in range(int(nlines)): #read the nlines of the *.mda file
matrix = np.fromfile(fidbin, np.float64,count=int(ncols)) #read all the values from one row
Indice_start = c*ncols
array[Indice_start:Indice_start+ncols]=matrix
fidbin.seek( fidbin.tell() + 8) #fid.tell() the actual read position + skip bytes (4 at the end of the line + 4 at the beginning of the second line)
fidbin.close()
它运行良好,但问题是对于大型二进制文件来说速度很慢。 有没有办法提高二进制文件的读取速度?
您可以使用结构化数据类型并通过一次调用 numpy.fromfile
来读取文件。例如,我的文件 qaz.mda
在每行开始和结束的四个字节标记之间有五列浮点值。以下是创建结构化数据类型和读取数据的方法。
首先,创建一个与每一行的格式匹配的数据类型:
In [547]: ncols = 5
In [548]: dt = np.dtype([('pre', np.int32), ('data', np.float64, ncols), ('post', np.int32)])
将文件读入结构化数组:
In [549]: a = np.fromfile("qaz.mda", dtype=dt)
In [550]: a
Out[550]:
array([(1, [0.0, 1.0, 2.0, 3.0, 4.0], 0),
(2, [5.0, 6.0, 7.0, 8.0, 9.0], 0),
(3, [10.0, 11.0, 12.0, 13.0, 14.0], 0),
(4, [15.0, 16.0, 17.0, 18.0, 19.0], 0),
(5, [20.0, 21.0, 22.0, 23.0, 24.0], 0)],
dtype=[('pre', '<i4'), ('data', '<f8', (5,)), ('post', '<i4')])
只提取我们想要的数据:
In [551]: data = a['data']
In [552]: data
Out[552]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
您也可以尝试 numpy.memmap
看看它是否提高了性能:
In [563]: a = np.memmap("qaz.mda", dtype=dt)
In [564]: a
Out[564]:
memmap([(1, [0.0, 1.0, 2.0, 3.0, 4.0], 0),
(2, [5.0, 6.0, 7.0, 8.0, 9.0], 0),
(3, [10.0, 11.0, 12.0, 13.0, 14.0], 0),
(4, [15.0, 16.0, 17.0, 18.0, 19.0], 0),
(5, [20.0, 21.0, 22.0, 23.0, 24.0], 0)],
dtype=[('pre', '<i4'), ('data', '<f8', (5,)), ('post', '<i4')])
In [565]: data = a['data']
In [566]: data
Out[566]:
memmap([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
注意上面的data
仍然是一个内存映射数组。为确保数据复制到内存中的数组中,可以使用numpy.copy
:
In [567]: data = np.copy(a['data'])
In [568]: data
Out[568]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
这是否有必要取决于您将如何在其余代码中使用该数组。