Writing a stream of 9 bit values as bytes to a file in C

无人久伴 提交于 2020-01-30 09:05:20

问题


I have an array with integer values from 0-511 (9 bits max). I am trying to write this to a file with fwrite.

For Example, with the array:

[257, 258, 259]
Which is 100000001, 100000010, 100000011

I am trying to write
100000001100000010100000011 + extra padding of 0s to the file 

But since fwrite limits writes to 1 byte at a time, I am not sure how to go about doing this. I am new to bitwise operations and am not how to separate out the individual bytes.


回答1:


You need a bit buffer.

Since you are writing 8 bits at the time, you must have data type that can hold at least 9+7 bits at minimum. uint16_t would do, but I recommend using size that would at least as big as your native int. Make sure you use unsigned types to avoid shifting issues.

uint32_t bitBuffer = 0;  // Our temporary bit storage
uint32_t count = 0;      // Number of bits in buffer

Let's assume we have single data:

uint32_t data9b = 257;  // 1 0000 0001

Adding bits to buffer is simple; just shift bits at the end of the buffer, and combine with OR.

bitBuffer |= (data9b << count); // At first iteration, shift does nothing
count += 9;                     // Update counter

After 9 bits are added, we can flush 8 bits to file.

while(count >= 8) {
    writeToFile(bitBuffer & 0xFF);  // Mask out lowest bits with AND
    bitBuffer >>= 8;                // Remove written bits
    count -= 8;                     // Fix counter
}

After each cycle you have 0 - 7 bits left over in the buffer. At the end of all data, if you finish with non-multiple of 8 bits, just write remaining contents of bitBuffer to file.

if(count > 0)
    writeToFile(bitBuffer);



回答2:


Ok, so did it using bit shifting, oring (can also do with *, '+', % and /) but shift is more appropriate / readable, imo.

// Your data, n is the number of 9-bits values
uint16_t dat[] = { 257, 258, 259 };
int i,n = sizeof(dat)/sizeof(*dat);

// out file
FILE *fp = fopen("f8.bin","w");

uint16_t one = 0;
int shift = 0;
uint8_t b;

// main loop
for(i=0 ; i<n ; i++) {
    b = (dat[i] << shift) | one; // one is remainder from previous value
    one = dat[i]>>(8-shift);     // Move the remaining MSb to the right
    shift = (shift+9) % 8;       // next shift
    fwrite(&b, 1, 1, fp);        // write our b byte
}
// remainder, always have a remainder
fwrite(&one, 1, 1, fp);
fclose(fp);

Had fun :-)



来源:https://stackoverflow.com/questions/47505922/writing-a-stream-of-9-bit-values-as-bytes-to-a-file-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!