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

后端 未结 2 2051
眼角桃花
眼角桃花 2021-01-25 05:54

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:

[         


        
相关标签:
2条回答
  • 2021-01-25 06:09

    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);
    
    0 讨论(0)
  • 2021-01-25 06:30

    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 :-)

    0 讨论(0)
提交回复
热议问题