Reading a binary file bit by bit

32,482

Solution 1

Adding to the first comment, you can try reading one byte at a time (declare a char variable and write there), and then use the bitwise operators >> and << to read bit by bit. Read more here: http://www.cprogramming.com/tutorial/bitwise_operators.html

Solution 2

I've implemented a couple of methods to read/write files bit by bit. Here they are. Whether it is viable or not for your use case, you have to decide that for yourself. I've tried to make the most readable, optimized code i could, not being a seasoned C developer (for now).

Internally, it uses a "bitCursor" to store information about previous bits that don't yet fit a full byte. It has who data fields: d stores data and s stores size, or the amount of bits stored in the cursor.

You have four functions:

  • newBitCursor(), which returns a bitCursor object with default values
    {0,0}. Such a cursor is needed at the beginning of a sequence of read/write operations to or from a file.
  • fwriteb(void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c), which writes sizeb rightmost bits of the value stored in ptr to fp.
  • fcloseb(FILE *fp, bitCursor *c), which writes a remaining byte, if the previous writes did not exactly encapsulate all data needed to be written, that is probably almost always the case...
  • freadb(void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c), which reads sizeb bits and bitwise ORs them to *ptr. (it is, therefore, your responsibility to init *ptr as 0)

More info is provided in the comments. Have Fun!

Edit: It has come to my knowledge today that when i made that i assumed Little Endian! :P Oops! It's always nice to realize how much of a noob i still am ;D.

Edit: GNU's Binary File Descriptors.

Solution 3

Many years ago, I wrote some I/O routines in C for a Huffman encoder. This needs to be able to read and write on the granularity of bits rather than bytes. I created functions analogous to read(2) and write(2) that could be asked to (say) read 13 bits from a stream. To encode, for example, bytes would be fed into the coder and variable numbers of bits would emerge the other side. I had a simple structure with a bit pointer into the current byte being read or written. Every time it went off the end, it flushed the completed byte out and reset the pointer to zero. Unfortunately that code is long gone, but it might be an idea to pull apart an open-source Huffman coder and see how the problem was solved there. Similarly, base64 coding takes 3 bytes of data and turns them into 4 (or vice versa).

Solution 4

Read the first two bytes from your a_file file pointer and check the bits in the least or greatest byte — depending on the endianness of your platform (x86 is little-endian) — using bitshift operators.

You can't really put bits into an array, as there isn't a datatype for bits. Rather than keeping 1's and 0's in an array, which is inefficient, it seems cheaper just to keep the two bytes in a two-element array (say, of type unsigned char *) and write functions to map those two bytes to one of 4096 (2^12) values-of-interest.

As a complication, on subsequent reads, if you want to fread through the pointer every 12 bits, you would read only one byte, using the left-over bits from the previous read to build a new 12-bit value. If there are no leftovers, you would need to read two bytes.

Your mapping functions would need to address the second case where bits were used from previous read, because the two bytes would need different mapping. To do this efficiently, a modulus on a read-counter could be used to swap between two mappings.

Solution 5

read 2 bytes and do bit wise operations will get it done for the next time read 2nd bytes onwards apply the bit-wise operations will get back you expected . . . .

Share:
32,482
Ryan
Author by

Ryan

Updated on February 22, 2020

Comments

  • Ryan
    Ryan about 4 years

    I know the function below:

    size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);
    

    It only reads byte by byte, my goal is to be able to read 12 bits at a time and then take them into an array. Any help or pointers would be greatly appreciated!

  • Alan Curry
    Alan Curry almost 12 years
    Every compression library has something like that. The one in ffmpeg/libavutil looks somewhat reusable.
  • Ryan
    Ryan almost 12 years
    that's what I'll be doing, I'll let you know how it works! Thanks alot!! This is probably the way to go!!