Чтение и интерпретация данных из двоичного файла в Python - PullRequest
22 голосов
/ 15 октября 2010

Я хочу прочитать файл побайтно и проверить, установлен ли последний бит каждого байта:

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

Я получаю ошибку:

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'

Есть идеи? Мне не удалось использовать struct и модули binascii.

Ответы [ 3 ]

39 голосов
/ 15 октября 2010

Попробуйте использовать тип bytearray (Python 2.6 и более поздние версии), он гораздо лучше подходит для работы с байтовыми данными.Ваш блок try будет просто:

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

или для создания списка результатов:

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

Это работает, потому что когда вы индексируете bytearray, вы просто возвращаетецелое число (0-255), тогда как, если вы просто читаете байт из файла, вы возвращаете одну строку символов и поэтому должны использовать ord для преобразования ее в целое число.


Если ваш файл слишком большой, чтобы его можно было удобно хранить в памяти (хотя я предполагаю, что это не так), тогда mmap можно использовать для создания bytearray из буфера:

import mmap
m = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ)
ba = bytearray(m)
8 голосов
/ 15 октября 2010

Вы хотите использовать ord вместо int:

if (ord(byte) & 0x01) == 0x01:
4 голосов
/ 15 октября 2010

В одну сторону:

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

В другую сторону:

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