2016-05-09 56 views
2

我有一個很大的二進制文件,我想在數組中讀取。 二進制文件的格式是:讀取二進制文件時提高速度

  • 在我沒有使用的每行的開始和結尾處都有一個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() 

它運作良好,但問題是,對於大型的二進制文件很慢。 有沒有辦法提高二進制文件的閱讀速度?

+0

您使用的是什麼Python版本? – niemmi

回答

2

您可以使用結構化數據類型並通過一次調用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.]]) 

無論是必要的取決於你將如何使用數組在你的代碼的其餘部分。

+0

謝謝你的回答! ....從16秒到0.18秒,速度的提高是驚人的 –