web-dev-qa-db-fra.com

Lire un fichier binaire en utilisant Numpy fromfile et un décalage donné

J'ai un fichier binaire qui contient des enregistrements de position d'un avion. Chaque enregistrement ressemble à:

0x00: Time, float32
0x04: X, float32 // X axis position
0x08: Y, float32 // Y axis position
0x0C: Elevation, float32
0x10: float32*4 = Quaternion (x,y,z axis and w scalar)
0x20: Distance, float32 (unused)

Ainsi, chaque enregistrement est long de 32 octets.

Je voudrais obtenir un tableau Numpy.

Au décalage 1859, il y a un entier 32 non signé (4 octets) qui indique le nombre d'éléments du tableau. 12019 dans mon cas.

Je m'en fous (pour l'instant) des données d'en-tête (avant l'offset 1859)

Le tableau ne démarre qu'au décalage 1863 (= 1859 + 4).

J'ai défini mon propre dtype Numpy comme

dtype = np.dtype([
    ("time", np.float32),
    ("PosX", np.float32),
    ("PosY", np.float32),
    ("Alt", np.float32),
    ("Qx", np.float32),
    ("Qy", np.float32),
    ("Qz", np.float32),
    ("Qw", np.float32),
    ("dist", np.float32),
])

Et je lis un fichier en utilisant fromfile:

a_bytes = np.fromfile(filename, dtype=dtype)

Mais je ne vois aucun paramètre à fournir à fromfile pour passer l'offset.

17
scls

Vous pouvez ouvrir le fichier avec un fichier standard python ouvert, puis chercher à ignorer l'en-tête, puis passer l'objet fichier à fromfile. Quelque chose comme ceci:

import numpy as np
import os

dtype = np.dtype([
    ("time", np.float32),
    ("PosX", np.float32),
    ("PosY", np.float32),
    ("Alt", np.float32),
    ("Qx", np.float32),
    ("Qy", np.float32),
    ("Qz", np.float32),
    ("Qw", np.float32),
    ("dist", np.float32),
])

f = open("myfile", "rb")
f.seek(1863, os.SEEK_SET)

data = np.fromfile(f, dtype=dtype)
print x 
18
reptilicus

J'ai rencontré un problème similaire, mais aucune des réponses ci-dessus ne m'a satisfait. J'avais besoin d'implémenter quelque chose comme une table virtuelle avec un très grand nombre d'enregistrements binaires qui occupaient potentiellement plus de mémoire que je ne peux me le permettre dans un tableau numpy. Ma question était donc de savoir comment lire et écrire un petit ensemble d'entiers de/vers un fichier binaire - un sous-ensemble d'un fichier dans un sous-ensemble de tableau numpy.

C'est une solution qui a fonctionné pour moi:

import numpy as np
recordLen = 10 # number of int64's per record
recordSize = recordLen * 8 # size of a record in bytes
memArray = np.zeros(recordLen, dtype=np.int64) # a buffer for 1 record

# Create a binary file and open it for write+read
with open('BinaryFile.dat', 'w+b') as file:
    # Writing the array into the file as record recordNo:
    recordNo = 200 # the index of a target record in the file
    file.seek(recordSize * recordNo)
    bytes = memArray.tobytes()
    file.write(bytes)

    # Reading a record recordNo from file into the memArray
    file.seek(recordSize * recordNo)
    bytes = file.read(recordSize)
    memArray = np.frombuffer(bytes, dtype=np.int64).copy()
    # Note copy() added to make the memArray mutable
3
Eugene Veselov