web-dev-qa-db-fra.com

Lecture et interprétation des données d'un fichier binaire en Python

Je veux lire un fichier octet par octet et vérifier si le dernier bit de chaque octet est défini:

#!/usr/bin/python

def main():
    fh = open('/tmp/test.txt', 'rb')
    try:
        byte = fh.read(1)
        while byte != "":
            if (int(byte,16) & 0x01) is 0x01:
                print 1
            else:
                print 0
            byte = fh.read(1)
    finally:
        fh.close

    fh.close()

if __name__ == "__main__":
        main()

L'erreur que j'obtiens est:

Traceback (most recent call last):
  File "./mini_01.py", line 21, in <module>
    main()
  File "./mini_01.py", line 10, in main
    if (int(byte,16) & 0x01) is 0x01:
ValueError: invalid literal for int() with base 16: '\xaf'

Quelqu'un a une idée? Je n'ai pas réussi à utiliser la structure et les modules binascii.

25
dubbaluga

Vous souhaitez utiliser ord au lieu de int:

if (ord(byte) & 0x01) == 0x01:
9
nmichaels

Essayez d'utiliser le type bytearray (Python 2.6 et versions ultérieures), il est beaucoup mieux adapté au traitement des données d'octets. Votre bloc try serait simplement:

ba = bytearray(fh.read())
for byte in ba:
    print byte & 1

ou pour créer une liste de résultats:

low_bit_list = [byte & 1 for byte in bytearray(fh.read())]

Cela fonctionne parce que lorsque vous indexez un bytearray vous récupérez simplement un entier (0-255), tandis que si vous venez de lire un octet du fichier, vous récupérez une chaîne de caractères unique et devez donc utiliser ord pour le convertir en entier.


Si votre fichier est trop volumineux pour être conservé confortablement en mémoire (même si je suppose que ce n'est pas le cas), alors un mmap pourrait être utilisé pour créer le bytearray à partir de un tampon:

import mmap
m = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ)
ba = bytearray(m)
45
Scott Griffiths

Une manière:

import array

filebytes= array.array('B')
filebytes.fromfile(open("/tmp/test.txt", "rb"))
if all(i & 1 for i in filebytes):
    # all file bytes are odd

Autrement:

fobj= open("/tmp/test.txt", "rb")

try:
    import functools
except ImportError:
    bytereader= lambda: fobj.read(1)
else:
    bytereader= functools.partial(fobj.read, 1)

if all(ord(byte) & 1 for byte in iter(bytereader, '')):
    # all bytes are odd
fobj.close()
4
tzot