2010-10-15 35 views
19

données à partir d'un fichier binaire que je veux lire un octet de fichier par octet et vérifiez si le dernier bit de chaque octet est défini:Lecture et interprétation en Python

#!/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 je reçois 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 les modules struct et binascii.

+2

Lisez http://stackoverflow.com/questions/306313/python-is-operator-prend-un-probablement-with-integers avant d'avoir * ce * travail et ouvrez une dupe de * cette * question;) – delnan

Répondre

7

Vous voulez utiliser ord au lieu de int:

if (ord(byte) & 0x01) == 0x01: 
+5

et vous vraiment devrait comparer les entiers avec '==', pas par leurs identités! –

+0

Bon point. J'y ai pensé, mais je ne l'ai pas changé quand j'ai collé ça ... réparé. – nmichaels

36

Essayez d'utiliser le type bytearray (Python 2.6 et versions ultérieures), il est beaucoup mieux adapté à traiter les données d'octets. Votre try bloc serait juste:

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 quand vous indexez une bytearray vous obtenez tout juste un entier (0-255), alors que Si vous venez de lire un octet du fichier, vous obtenez une seule chaîne de caractères et devez donc utiliser ord pour le convertir en entier.


Si votre fichier est trop grand pour tenir confortablement dans la mémoire (si je devine que ce n'est pas) alors un mmap pourrait être utilisé pour créer le bytearray à partir d'un tampon:

import mmap 
m = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ) 
ba = bytearray(m) 
+2

+1 pour la solution de gros fichier, j'ai été sauvé de beaucoup de cheveux-déchirement. Vous, Monsieur, êtes un gentleman et un savant. – brichins

3

une façon:

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 

une autre façon:

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()