2010-10-15 21 views
19

quiero leer un byte de archivos a byte y comprobar si el último bit de cada byte se establece:Lectura e interpretación de los datos de un archivo binario 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() 

El error que consigo es:

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' 

¿Alguien una idea? No tuve éxito usando los módulos struct y binascii.

+2

Lea http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers antes de obtener * this * funcionando y abra una trampa de * esa * pregunta;) – delnan

Respuesta

7

que desea utilizar en lugar de ordint:

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

y usted realmente debería comparar enteros con '==', ¡no por sus identidades! –

+0

Buen punto. Lo pensé, pero no lo cambié cuando pegué eso ... arreglado. – nmichaels

36

intente utilizar el tipo bytearray (Python 2.6 y posterior), que es mucho más adecuado para tratar con datos byte. Su bloque de try sería simplemente:

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

o para crear una lista de resultados:

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

Esto funciona porque cuando un índice de bytearray que acaba de llegar de vuelta un número entero (0-255), mientras si solo lees un byte del archivo, obtienes una cadena de caracteres única y necesitas usar ord para convertirla en un entero.


Si el archivo es demasiado grande como para albergar cómodamente en la memoria (aunque supongo que no es) a continuación, un mmap podrían utilizarse para crear el bytearray desde un buffer:

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

+1 para la solución de archivos de gran tamaño, me salvó de lagrimear mucho. Usted, señor, es un caballero y un erudito. – brichins

3

una manera:

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 

Otra forma:

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