2010-10-15 8 views
19

voglio leggere un file byte per byte e verificare se è impostato l'ultimo bit di ogni byte:Lettura e interpretazione dei dati da un file binario in 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'errore che ottengo è:

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' 

Qualcuno un'idea? Non ho avuto successo usando i moduli struct e binascii.

+2

Leggi http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers prima che venga * this * funzionante e apri un duplicato di * that * question;) – delnan

risposta

7

si desidera utilizzare ord invece di int:

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

e tu davvero dovrebbe confrontare gli interi con '==', non con le loro identità! –

+0

Buon punto. Ci ho pensato, ma non l'ho modificato quando l'ho incollato ... risolto. – nmichaels

36

utilizzare il tipo di bytearray (Python 2.6 e successivi), è molto più adatta a trattare con i dati di byte. Il tuo blocco try sarebbe solo:

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

o per creare un elenco di risultati:

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

Questo funziona perché quando si indice un bytearray basta avere indietro un intero (0-255), mentre se si legge un byte dal file si ottiene una stringa di caratteri singola e quindi è necessario utilizzare ord per convertirlo in un numero intero.


Se il file è troppo grande per contenere comodamente in memoria (anche se sto cercando di indovinare che non è) allora un mmap potrebbe essere utilizzato per creare il bytearray da un buffer:

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

+1 per la soluzione di file di grandi dimensioni, mi è stato salvato da molti strappi. Lei signore è un gentiluomo e uno studioso. – brichins

3

Un modo:

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 

Un altro modo:

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