2012-03-30 63 views
10

Tôi đang đọc một tập tin nhị phân trong python và tài liệu cho các định dạng tập tin nói:Python: Extracting bit từ một byte

Cờ (ở dạng nhị phân) Ý nghĩa

1 nnn nnnn Chỉ ra rằng có là một byte dữ liệu để theo dõi đó là để được nhân đôi nnn nnnn (tối đa 127) lần.

0 nnn nnnn Cho biết rằng có nnn nnnn byte của hình ảnh dữ liệu cần theo dõi (tối đa 127 byte) và rằng không có trùng lặp.

n 000 0000 Kết thúc trường dòng. Cho biết kết thúc của một dòng ghi . Giá trị của n có thể là số không hoặc một. Lưu ý rằng kết thúc của trường dòng là bắt buộc và rằng nó được phản ánh trong độ dài của dòng ghi trường được đề cập ở trên.

Khi đọc các tập tin tôi hy vọng các byte Tôi đang ở trở 1 nnn nnnn nơi phần nnn nnnn nên 50.

tôi đã có thể làm khi sử dụng này như sau:

flag = byte >> 7 
numbytes = int(bin(byte)[3:], 2) 

Nhưng tính toán số byte cảm thấy giống như một giải pháp rẻ tiền.

Tôi có thể thực hiện nhiều phép tính bit hơn để thực hiện việc tính toán số không?

Bạn sẽ tiếp cận điều này bằng cách nào?

+0

liên quan: [Sử dụng Python Làm thế nào tôi có thể đọc các bit trong một byte?] (Http://stackoverflow.com/q/2576712/4279) – jfs

Trả lời

7

Bạn có thể lột bit hàng đầu sử dụng một mặt nạ ANDed với một byte từ tập tin. Điều đó sẽ để lại cho bạn giá trị của các bit còn lại:

mask = 0b01111111 
byte_from_file = 0b10101010 
value = mask & byte_from_file 
print bin(value) 
>> 0b101010 
print value 
>> 42 

Tôi tìm số nhị phân dễ hiểu hơn hex khi thực hiện bit-masking.

EDIT: Hơi hoàn chỉnh hơn ví dụ cho trường hợp sử dụng của bạn:

LEADING_BIT_MASK = 0b10000000 
VALUE_MASK = 0b01111111 

bytes = [0b10101010, 0b01010101, 0b0000000, 0b10000000] 

for byte in bytes: 
    value = byte & VALUE_MASK 
    has_leading_bit = byte & LEADING_BIT_MASK 
    if value == 0: 
     print "EOL" 
    elif has_leading_bit: 
     print "leading one", value 
    elif not has_leading_bit: 
     print "leading zero", value 
+0

Cảm ơn bạn. Tôi cũng thích số nhị phân trong trường hợp này. –

+0

@EvanBorgstrom Trên Python 3, bạn có thể viết: 'dữ liệu = b '\ xaa \ x55 \ x00 \ x80'' và' cho byte trong dữ liệu: ... '. Không sử dụng tên 'byte', nó là một kiểu nội trang. – jfs

9

Phương pháp cổ điển của kiểm tra xem một chút được thiết lập, là sử dụng hệ nhị phân "và" điều hành, tức là

x = 10 # 1010 in binary 
if x & 0b10 != 0: 
    print('Second bit is set') 

Để kiểm tra, cho dù n^chút thứ được thiết lập, sử dụng sức mạnh của hai, tức là

def is_set(x, n): 
    return x & 2**n != 0 

is_set(10, 1) # 1 because we count from 0th bit 
>>> True 
+0

Cảm ơn, nhưng điều đó không thực sự trả lời câu hỏi của tôi. Cho byte = 178, bạn sẽ trích xuất cờ == 1 & numbytes == 50 như thế nào? –

+1

+1: nhưng không cần phần! = 0, 'nếu x & 0b10' là đủ. – tom10

+1

'! = 0' không phải là khá xấu như' == True', nhưng nó là gần. :) –

0

không chắc là tôi có bạn một cách chính xác, nhưng nếu tôi đã làm, điều này sẽ làm các trick:

>>> x = 154 #just an example 
>>> flag = x >> 1 
>>> flag 
1 
>>> nb = x & 127 
>>> nb 
26 
1

Nếu tôi đọc mô tả của bạn một cách chính xác:

if (byte & 0x80) != 0: 
    num_bytes = byte & 0x7F 
0

Bạn có thể làm điều đó như thế này:

def GetVal(b): 
    # mask off the most significant bit, see if it's set 
    flag = b & 0x80 == 0x80 
    # then look at the lower 7 bits in the byte. 
    count = b & 0x7f 
    # return a tuple indicating the state of the high bit, and the 
    # remaining integer value without the high bit. 
    return (flag, count) 

>>> testVal = 50 + 0x80 
>>> GetVal(testVal) 
(True, 50) 
0

có bạn đi:

class ControlWord(object): 
    """Helper class to deal with control words. 

    Bit setting and checking methods are implemented. 
    """ 
    def __init__(self, value = 0): 
     self.value = int(value) 
    def set_bit(self, bit): 
     self.value |= bit 
    def check_bit(self, bit): 
     return self.value & bit != 0 
    def clear_bit(self, bit):  
     self.value &= ~bit 
0

Thay vì int (bin (byte) [3:], 2), bạn có thể chỉ cần sử dụng: int (bin (byte >> 1), 2)

Các vấn đề liên quan