Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing bits to a binary file

I have 23 bits represented as a string, and I need to write this string to a binary file as 4 bytes. The last byte is always 0. The following code works (Python 3.3), but it doesn't feel very elegant (I'm rather new to Python and programming). Do you have any tips of making it better? It seems a for-loop might be useful, but how do I do the slicing within the loop without getting a IndexError? Note that that when I extract the bits into a byte, I reverse the bit-order.

from array import array

bin_array = array("B")
bits = "10111111111111111011110"    #Example string. It's always 23 bits
byte1 = bits[:8][::-1]
byte2 = bits[8:16][::-1]
byte3 = bits[16:][::-1]
bin_array.append(int(byte1, 2))
bin_array.append(int(byte2, 2))
bin_array.append(int(byte3, 2))
bin_array.append(0)

with open("test.bnr", "wb") as f:
    f.write(bytes(bin_array))

# Writes [253, 255, 61, 0] to the file
like image 743
Olav Avatar asked Jan 19 '14 18:01

Olav


2 Answers

You can treat it as an int, then create the 4 bytes as follows:

>>> bits = "10111111111111111011110"
>>> int(bits[::-1], 2).to_bytes(4, 'little')
b'\xfd\xff=\x00'
like image 180
Jon Clements Avatar answered Oct 04 '22 15:10

Jon Clements


The struct module was designed for exactly this sort of thing — consider the following in which the conversion to bytes has been broken down into some unnecessary intermediate steps to make understanding it clearer:

import struct

bits = "10111111111111111011110"  # example string. It's always 23 bits
int_value = int(bits[::-1], base=2)
bin_array = struct.pack('i', int_value)
with open("test.bnr", "wb") as f:
    f.write(bin_array)

A harder-to-read, but shorter, way would be:

bits = "10111111111111111011110"  # example string. It's always 23 bits
with open("test.bnr", "wb") as f:
    f.write(struct.pack('i', int(bits[::-1], 2)))
like image 39
martineau Avatar answered Oct 04 '22 16:10

martineau