Lire un fichier binaire morceau par morceau

2 réponses
Avatar
Kevin Denis
Bonjour,

je cherche à lire différents fichiers binaires dont je connais le
format.
Pour les reconnaitre, j'ai besoin de lire quelques octets, puis
de les vérifier, et selon les cas d'en lire plus ou moins ensuite,
etc..
Je pense a une fonction "walker" qui me lit le fichier octet après
octet et itérer mais n'y a t'il pas un moyen simple de lire des
séquences d'octets à des zones arbitraires du fichier?

Merci
--
Kevin

2 réponses

Avatar
Damien Wyart
* Kevin Denis in fr.comp.lang.python:

je cherche à lire différents fichiers binaires dont je connais le
format. Pour les reconnaitre, j'ai besoin de lire quelques octets,
puis de les vérifier, et selon les cas d'en lire plus ou moins
ensuite, etc..



Sur ce thème, il y a pas mal de choses sur StackOverflow :

http://stackoverflow.com/questions/1035340/reading-binary-file-in-python
http://stackoverflow.com/questions/2365998/using-python-how-do-i-read-and-extract-data-from-a-binary-data-file-with-multip
http://stackoverflow.com/questions/6132012/reading-structure-binary-data-in-python
http://stackoverflow.com/questions/3507925/read-40-bytes-of-binary-data-as-ascii-text
http://stackoverflow.com/questions/3943149/reading-and-interpreting-data-from-a-binary-file-in-python
http://stackoverflow.com/questions/2872381/how-to-read-a-file-byte-by-byte-in-python-and-how-to-print-a-bytelist-as-a-binar
http://stackoverflow.com/questions/8710456/reading-a-binary-file-with-python

Je pense a une fonction "walker" qui me lit le fichier octet après
octet et itérer mais n'y a t'il pas un moyen simple de lire des
séquences d'octets à des zones arbitraires du fichier?



seek() et read() sur l'object fichier peuvent convenir ; si le fichier
est "petit", tu peux aussi le lire en une fois et travailler sur les
données directement en mémoire. Il y a quelques exemples dans les
articles cité au-dessus.

--
DW
Avatar
Pierre Maurette
Kevin Denis :
Bonjour,

je cherche à lire différents fichiers binaires dont je connais le
format.
Pour les reconnaitre, j'ai besoin de lire quelques octets, puis
de les vérifier, et selon les cas d'en lire plus ou moins ensuite,
etc..



Pour répondre, j'ai en tête un exemple certainement très proche,
lecture d'un fichier .iso, identification de son format, et si possible
extraction de son contenu. Le tout sur site (1&1).

Je pense a une fonction "walker" qui me lit le fichier octet après
octet et itérer mais n'y a t'il pas un moyen simple de lire des
séquences d'octets à des zones arbitraires du fichier?



Je ne comprends pas trop le souci. Pour avoir un code plus lisible,
vous pouvez commencer par utiliser systématiquement une fonction comme:

def myRead(fileobject, offset, size):
fileobject.seek(offset)
return fileobject.read(size)

Intuitivement, il n'y a pas de surcoût significatif à faire un
file.seek() avant un file.read(). Surtout pour des lectures
ponctuelles, vous pouvez même négliger os.SEEK_CUR et le remplacer
éventuellement par file.tell(), si ça vous convient mieux.

En revanche vous aurez certainement avantage à limiter raisonnablement
le nombre des opérations de lecture. Simplement en lisant un morceau,
disons une table, et en utilisant ensuite les slices pour l'extraction.

Pensez à binascii.hexlify pour récupérer des valeurs numériques. Un
exemple de début de boite à outils:

from binascii import hexlify

""" returns an integer value from a n bytes list in 'little endian' """
def intvallittle(zone):
return int(hexlify(zone[::-1]), 16)

""" returns an integer value from a n bytes list in 'big endian' """
def intvalbig(zone):
return int(hexlify(zone), 16)

""" returns an integer value from a 2n bytes list in 'both endian' """
def intvalboth(zone):
return int(hexlify(zone[len(zone)/2:]), 16)

""" debug - returns a string 'decimal (hexadecimal)' from an integer
value """
def dispint(val):
return '%d (0x%04X)' % (val, val)

""" debug - returns a string 'hex.hex. ... .hex' from a bytes slice """
def rawdata(zone):
return '.'.join(map(hex,map(ord, zone)))


D'un autre coté, c'est quand il s'agira de récupérer de grosses données
à partir de gros fichiers qu'il faudra sans doute contourner la lecture
directe et mettre en place une lecture séquentielle. Avant la
performance, c'est la limitation de la taille des objets qui sera une
limitation. Dans le cas d'un hébergement mutualisé, cette limitation
sera peut-être non négociable et même difficile à connaitre. La
littérature est abondante sur le sujet, avec Google essayer /python/
/file.read/ /chunk/ etc. Un exemple non publiable et écrit avec les
pieds (fo est extérieur à la fonction et au minimum mal nommé):

""" create file 'name' filled with dataL bytes read from offset dataB
in fo
read and write-append is chunked by chunkSZ bytes chunks
"""
def copyFile(dataB, dataL, chunkSZ, name):
if dataL <= chunkSZ:
fo.seek(dataB, os.SEEK_SET)
open(name, 'wb').write(fo.read(dataL))
else:
dataE = dataB + dataL
fo.seek(dataB, os.SEEK_SET)
open(name, 'wb').write(fo.read(chunkSZ))
if dataL > chunkSZ:
f = open(name, 'ab')
while 1:
dataB += chunkSZ
if dataB > dataE:
break
fo.seek(dataB, os.SEEK_SET)
data = fo.read(min(chunkSZ, dataE - dataB))
f.write(data)

--
Pierre Maurette