Reading a binary file bit by bit
Asked Answered
I

6

10

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!

Iridize answered 27/7, 2012 at 1:18 Comment(2)
Sorry, one byte at a time is the smallest granularity you can do. You'll have to resort to (shudder) actual programming to split out 12-bit entities.Nonentity
I think you want this answer: #142025Foretopgallant
F
8

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

Freudberg answered 27/7, 2012 at 1:24 Comment(1)
that's what I'll be doing, I'll let you know how it works! Thanks alot!! This is probably the way to go!!Iridize
G
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).

Guttural answered 27/7, 2012 at 3:59 Comment(1)
Every compression library has something like that. The one in ffmpeg/libavutil looks somewhat reusable.Subcontinent
S
3

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.

Sidsida answered 30/3, 2016 at 19:30 Comment(0)
T
2

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.

Totten answered 27/7, 2012 at 1:36 Comment(0)
B
1

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

Bloomers answered 27/7, 2012 at 4:27 Comment(0)
P
0

For your problem you can see this demo program which read 2byte but actual information is only 12 bit.As well as this type of things are used it bit wise access.

fwrite() is a standard library function which take the size argument as byte and of type int.So it is not possible exactly 12bit read.If the file you create then create like below as well as read as below it solve your problem.

If that file is special file which not written by you then follow the standard provided for that file to read I think they also writing like this only.Or you can provide the axact where it I may help you.

#include<stdio.h>
#include<stdlib.h>
struct node
 {
   int data:12;

 }NODE;
int main()
{
   FILE *fp;
   fp=fopen("t","w");
   NODE.data=1024;
   printf("%d\n",NODE.data);
   fwrite(&NODE,sizeof(NODE),1,fp);
   NODE.data=0;
   NODE.data=2048;
   printf("%d\n",(unsigned)NODE.data);
   fwrite(&NODE,sizeof(NODE),1,fp);
   fclose(fp);
   fp=fopen("t","r");
   fread(&NODE,sizeof(NODE),1,fp);
   printf("%d\n",NODE.data);
   fread(&NODE,sizeof(NODE),1,fp);
   printf("%d\n",NODE.data);
   fclose(fp);
}
Prater answered 28/7, 2012 at 12:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.