2010-04-05 39 views

Trả lời

24

Đọc các bit từ một tệp, bit thấp trước tiên.

def bits(f): 
    bytes = (ord(b) for b in f.read()) 
    for b in bytes: 
     for i in xrange(8): 
      yield (b >> i) & 1 

for b in bits(open('binary-file.bin', 'r')): 
    print b 
+0

Thử nghiệm này (btw byte là ít endian) và ord ('\ x04') trả về 4 sẽ trả về chuỗi bit '0000100' sử dụng mã của bạn tôi nhận được '000100000' – David

+0

oops i có nghĩa là tôi nhận được '00100000' với mã của bạn – David

+1

Nó cung cấp cho bit thấp đầu tiên (đó là tự nhiên, vì nó cũng cung cấp cho byte thấp đầu tiên). Nhưng nếu bạn muốn thứ tự khác, bạn có thể thay đổi 'xrange (8)' thành 'đảo ngược (xrange (8))'. –

18

Đơn vị nhỏ nhất bạn có thể làm việc là một byte. Để làm việc ở mức bit bạn cần sử dụng bitwise operators.

x = 3 
#Check if the 1st bit is set: 
x&1 != 0 
#Returns True 

#Check if the 2nd bit is set: 
x&2 != 0 
#Returns True 

#Check if the 3rd bit is set: 
x&4 != 0 
#Returns False 
+2

Bạn có nhớ thêm thông tin, vì OP rõ ràng có vẻ giống người mới bắt đầu không? –

+0

Chắc chắn tôi đang đến từ một nền tảng MATLAB và không thể tìm thấy một 'ubit1' typecode cho python. Tôi đã sử dụng các mục sau: f = open ('tên tệp', 'rb') var = f.read (1) trả về var làm chuỗi giá trị hex '\ x04' làm cách nào để có được nhị phân đại diện của chuỗi? – David

+0

@ David: Tôi thấy, đã được đề cập đến bởi câu trả lời được chấp nhận. –

10

Bạn sẽ không thể đọc từng bit một - bạn phải đọc từng byte một. Tuy nhiên, bạn có thể dễ dàng trích xuất các bit ra:

f = open("myfile", 'rb') 
# read one byte 
byte = f.read(1) 
# convert the byte to an integer representation 
byte = ord(byte) 
# now convert to string of 1s and 0s 
byte = bin(byte)[2:].rjust(8, '0') 
# now byte contains a string with 0s and 1s 
for bit in byte: 
    print bit 
+0

thử nó và cho ví dụ nơi byte = '\ 0x04' mã trên trả về \t '0b' – David

+0

@ David OOPS! Hãy để tôi sửa lỗi đó. Xin lỗi .... (sửa) Ok, nó đã được sửa rồi. Nên làm việc. –

+0

Cảm ơn mã của bạn bây giờ cho byte = 100 là đại diện chính xác 2 đại diện của ord ('\ 0x04') = 4 nhưng không nên đọc byte là '00000100' – David

2

Có hai cách có thể để trả lại bit thứ i của một byte. "Bit đầu tiên" có thể tham chiếu đến bit thứ tự cao hoặc nó có thể tham chiếu đến bit thứ tự thấp hơn.

Đây là hàm nhận chuỗi và chỉ mục làm tham số và trả về giá trị của bit tại vị trí đó. Như được viết, nó xử lý bit thứ tự thấp như bit đầu tiên. Nếu bạn muốn bit thứ tự cao đầu tiên, chỉ cần bỏ ghi chú dòng được chỉ định.

def bit_from_string(string, index): 
     i, j = divmod(index, 8) 

     # Uncomment this if you want the high-order bit first 
     # j = 8 - j 

     if ord(string[i]) & (1 << j): 
       return 1 
     else: 
       return 0 

Việc lập chỉ mục bắt đầu từ 0, bạn có thể điều chỉnh chỉ mục trong hàm trước khi gọi divmod.

Ví dụ sử dụng:

>>> for i in range(8): 
>>>  print i, bit_from_string('\x04', i) 
0 0 
1 0 
2 1 
3 0 
4 0 
5 0 
6 0 
7 0 

Bây giờ, đối với cách thức hoạt động:

Một chuỗi gồm byte 8-bit, vì vậy đầu tiên chúng tôi sử dụng divmod() để phá vỡ các chỉ số thành đến các bộ phận:

  • i: chỉ số của byte đúng trong chuỗi
  • j: chỉ số của các bit đúng w ithin rằng byte

Chúng tôi sử dụng hàm ord() để chuyển đổi ký tự tại string[i] thành một số nguyên. Sau đó, (1 << j) tính giá trị của bit thứ j bằng cách dịch chuyển trái 1 theo j. Cuối cùng, chúng tôi sử dụng bitwise-và để kiểm tra nếu bit đó được thiết lập. Nếu trả lại 1, nếu không trả lại 0.

+0

OK! cảm ơn cho các chi tiết trong bình luận của bạn tôi nhìn vào các nhà khai thác bit thay đổi nhưng không thể nhìn thấy nó hoạt động như thế nào cho điều này.Câu trả lời của bạn giúp làm rõ các toán tử bitwise và cách tiếp cận. Cảm ơn – David

+0

Daniel cảm ơn vì giải pháp chung ở trên. – David

0

này là khá nhanh, tôi sẽ nghĩ:

import itertools 
data = range(10) 
format = "{:0>8b}".format 
newdata = (False if n == '0' else True for n in itertools.chain.from_iterable(map(format, data))) 
print(newdata) # prints tons of True and False 
0

Giả sử bạn có một tệp có tên là bloom_filter.bin trong đó c ontains một mảng bit và bạn muốn đọc toàn bộ tập tin và sử dụng các bit trong một mảng.

Đầu tiên tạo ra các mảng nơi các bit sẽ được lưu trữ sau khi đọc,

from bitarray import bitarray 
a=bitarray(size)   #same as the number of bits in the file 

Mở tập tin, sử dụng mở hoặc với bất cứ điều gì là tốt ... Tôi gắn bó với mở ở đây,

f=open('bloom_filter.bin','rb') 

Bây giờ tải tất cả các bit vào mảng 'a' tại một shot sử dụng,

f.readinto(a) 

'a' hiện là một bitarray chứa tất cả các bit

+0

bạn phải cài đặt mô-đun bitarray đầu tiên: pip install bitarray – vac

4

Để đọc một byte từ một tệp: bytestring = open(filename, 'rb').read(1). Lưu ý: tệp được mở ở chế độ nhị phân.

Để có được bit, chuyển đổi bytestring vào một số nguyên: byte = bytestring[0] (Python 3) hoặc byte = ord(bytestring[0]) (Python 2) và trích xuất các bit mong muốn: (byte >> i) & 1:

>>> for i in range(8): (b'a'[0] >> i) & 1 
... 
1 
0 
0 
0 
0 
1 
1 
0 
>>> bin(b'a'[0]) 
'0b1100001' 
2

Tham gia một số các câu trả lời trước tôi sẽ sử dụng :

[int(i) for i in "{0:08b}".format(byte)] 

Đối với mỗi byte đọc từ tệp. Kết quả cho ví dụ về byte 0x88 là:

>>> [int(i) for i in "{0:08b}".format(0x88)] 
[1, 0, 0, 0, 1, 0, 0, 0] 

Bạn có thể gán cho biến và làm việc theo yêu cầu ban đầu của bạn. "{0,08}" là để đảm bảo độ dài byte đầy đủ

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