2010-10-15 14 views
19

in Python Daten aus einer Binärdatei zu interpretieren ich eine Datei Byte für Byte lesen möchten, und überprüfen, ob das letzte Bit jedes Byte festgelegt ist:Lesen und

#!/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() 

Der Fehler, den ich bekommen ist:

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' 

Wer eine Idee? Es ist mir nicht gelungen, die Module struct und binascii zu verwenden.

+2

Lies http://stackoverflow.com/questions/306313/python-is-operator-behaves-unerwarteter-mit-integers, bevor du * diese * Arbeit erschaffst und öffnest einen Dip von * dieser * Frage;) – delnan

Antwort

7

Sie wollen ord verwenden statt int:

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

und du wirklich sollte ganze Zahlen mit '==' vergleichen, nicht mit ihren Identitäten! –

+0

Guter Punkt. Ich habe darüber nachgedacht, habe es aber nicht geändert, als ich das eingefügt habe ... behoben. – nmichaels

36

Versuchen Sie, die bytearray Typ (Python 2.6 und höher) verwenden, ist es viel besser geeignet, mit Byte-Daten zu tun haben. Ihr try Block wäre nur:

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

oder eine Liste der Ergebnisse zu erstellen:

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

Dies funktioniert, weil, wenn Sie Index ein bytearray Sie bekommen gerade eine ganze Zahl (0-255), während Wenn Sie nur ein Byte aus der Datei lesen, erhalten Sie eine einzelne Zeichenkette zurück und müssen ord verwenden, um sie in eine ganze Zahl zu konvertieren.


Wenn Ihre Datei ist zu groß, bequem im Speicher zu halten (obwohl ich es bin zu raten, nicht), dann ein mmap verwendet werden, um die bytearray von einem Puffer zu erstellen:

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

+1 für die große Datei Lösung, wurde ich vor viel Haarriss gerettet. Sie sind ein Gentleman und ein Gelehrter. – brichins

3

Eine Möglichkeit:

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 

Ein anderer Weg:

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