2015-07-03 6 views
6

Ich möchte eine Binärdatei in Python lesen, deren genaues Layout in der Binärdatei selbst gespeichert ist.Wie kann ich aufeinanderfolgende Arrays aus einer Binärdatei mit `np.fromfile` lesen?

Die Datei enthält eine Sequenz von zweidimensionalen Arrays, wobei die Zeilen- und Spaltenabmessungen jedes Arrays als ein Paar Ganzzahlen vor dem Inhalt gespeichert sind. Ich möchte nacheinander alle in der Datei enthaltenen Arrays lesen.

Ich weiß, dass dies mit f = open("myfile", "rb") und f.read(numberofbytes) getan werden kann, aber das ist ziemlich ungeschickt, weil ich dann die Ausgabe in sinnvolle Datenstrukturen konvertieren müsste. Ich möchte numpy np.fromfile mit einer benutzerdefinierten dtype verwenden, aber habe keine Möglichkeit gefunden, einen Teil der Datei zu lesen, lassen Sie es geöffnet, und dann weiterlesen mit einer modifizierten dtype.

Ich weiß, ich kann os zu f.seek(numberofbytes, os.SEEK_SET) und np.fromfile mehrere Male verwenden, aber das würde bedeuten, viel unnötiges Herumspringen in der Datei.

Kurz gesagt, ich will fread (oder zumindest so etwas wie C++ ifstreamread) die MATLAB.

Was ist der beste Weg, dies zu tun?

+0

Können Sie das Dateiformat beschreiben? Es ist schwierig, einen bestimmten Ansatz zu empfehlen, ohne etwas über die Datei selbst zu wissen. –

+0

es ist eine rohe Binärdatei, es enthält Matrizen als Doppel aus einem C++ - Programm, und Ganzzahlen, die die Größe der Matrizen beschreiben – jacob

+0

Enthält eine einzelne Datei mehrere Arrays oder gibt es nur ein Array pro Datei? Sind die Array-Dimensionen in einer Kopfzeile am Anfang der Datei angegeben? Kannst du den Header beschreiben? –

Antwort

4

Sie können ein geöffnetes Dateiobjekt an np.fromfile übergeben, die Dimensionen des ersten Arrays lesen und anschließend den Arrayinhalt lesen (erneut unter Verwendung von np.fromfile) und den Vorgang für weitere Arrays innerhalb derselben Datei wiederholen.

Zum Beispiel:

import numpy as np 
import os 

def iter_arrays(fname, array_ndim=2, dim_dtype=np.int, array_dtype=np.double): 

    with open(fname, 'rb') as f: 
     fsize = os.fstat(f.fileno()).st_size 

     # while we haven't yet reached the end of the file... 
     while f.tell() < fsize: 

      # get the dimensions for this array 
      dims = np.fromfile(f, dim_dtype, array_ndim) 

      # get the array contents 
      yield np.fromfile(f, array_dtype, np.prod(dims)).reshape(dims) 

Beispiel Nutzung:

# write some random arrays to an example binary file 
x = np.random.randn(100, 200) 
y = np.random.randn(300, 400) 

with open('/tmp/testbin', 'wb') as f: 
    np.array(x.shape).tofile(f) 
    x.tofile(f) 
    np.array(y.shape).tofile(f) 
    y.tofile(f) 

# read the contents back 
x1, y1 = iter_arrays('/tmp/testbin') 

# check that they match the input arrays 
assert np.allclose(x, x1) and np.allclose(y, y1) 

Wenn die Arrays groß sind, können Sie sich anschauen sollten np.memmap mit dem offset= Parameter anstelle von np.fromfile unter Verwendung der Inhalte der Arrays zu erhalten als Speicherkarten, anstatt sie in den Arbeitsspeicher zu laden.

Verwandte Themen