Как читать файл, в котором биты не выровнены по границе байта в C - PullRequest
0 голосов
/ 25 мая 2020

Итак, у меня есть двоичный файл, который я хочу прочитать, который имеет 256 сегментов следующей структуры:

  • Первый байт: целое число, представляющее длину битов поля следуя ему, что вам нужно прочитать. Оно не обязательно заканчивается границей байта
  • Переменное количество бит: поле, которое вы хотите прочитать. Он не обязательно заканчивается границей байта.

Файл заканчивается заполненными нулями, так что он заканчивается на границе байта.

Я изо всех сил пытаюсь найти идеал метод, который включает чтение как можно меньшего количества отдельных битов. Я думаю, может быть, сначала прочитать длину, разделить это значение на 8 и прочитать это количество байтов следующим, а затем использовать остаток от предыдущей операции (если есть) для чтения остальной части поля бит за битом. Однако я не уверен, что это идеальный метод. Есть предложения?

Edit: Прикреплена ссылка на файлы. Читаемый файл - это формат, в котором я хотел бы распечатать двоичный файл. Чтобы взять пример из желаемого вывода:

  • длина для 9 c: 4
  • код для 9 c: 1101

4 будет первым байтом, прочитанным из двоичного файла, а 1101 будет переменным количеством битов

https://ln2.sync.com/dl/e85dc8b40/3f5wbhaq-kxz3ijv8-wuts3t32-442gbsh2

1 Ответ

0 голосов
/ 26 мая 2020

Наивный метод отлично работает (для небольших файлов). На самом деле ввод полностью не выровнен, всего лишь серия битов, без каких-либо дополнений.

[Я удалю этот ответ через 1 минуту, потому что я не хочу делать домашнее задание]


#include <stdio.h>
#include <stdlib.h>

#define the_path "/home/Download/binary_file.dict"

struct bitfile {
        FILE *fp;
        unsigned char byte;
        unsigned char left;
        };

struct bitfile * bfopen(char *path)
{
struct bitfile *bp;

bp = malloc(sizeof *bp);
bp->fp = fopen(path, "rb" );
bp->byte = 0;
bp->left = 0;

return bp;
}
int bfclose(struct bitfile * bp)
{
int rc;
rc = fclose(bp->fp);
free(bp);
return rc;
}

int bfgetb(struct bitfile * bp)
{
int ch;
if (!bp->left) {
        ch = fgetc(bp->fp);
        if (ch < 0) return EOF;
        bp->byte = ch;
        bp->left = 8;
        }
bp->left -= 1;
ch = bp->byte & (1u << bp->left) ? 1 : 0;
// bp->byte >>= 1;
return ch;
}

void bfflush(struct bitfile * bp)
{
bp->left =0;
}

unsigned bp_get_n( struct bitfile *bp, unsigned bitcount)
{
unsigned val=0;

while(bitcount--) {
        int ch;
        ch = bfgetb(bp);
        if (ch < 0) return EOF;
        val <<=1;
        val |= ch;
        }
return val;
}

int main(void)
{
struct bitfile *bp;
int ch;
unsigned iseg, ibit, nbit;

bp = bfopen( the_path);

for (iseg =0; iseg <16*16; iseg++) {
        // bfflush(bp);
        nbit = bp_get_n(bp, 8);
        fprintf(stdout, "Seg%u: %u bits\n", iseg, nbit);
        fprintf(stdout, "payload:");
        for (ibit=0; ibit < nbit; ibit++) {
                ch = bfgetb(bp);
                if (ch < 0) break;
                fputc( '0'+ ch, stdout);
                }
        fprintf(stdout, ".\n");
        }
bfclose(bp);
return 0;
}
...