【问题标题】:Reading binary data 40 bits at a time一次读取 40 位二进制数据
【发布时间】:2017-01-15 20:25:17
【问题描述】:

我正在尝试一次访问 10 位二进制数据。我认为最好的方法是以 unsigned long long 读取 40 位,然后使用位掩码来访问所需的数据。我的努力似乎读了 64 位,我想知道是否有人能指出我哪里出错了。谢谢。

FILE * pFile;
long lSize;
unsigned long long * buffer;
size_t result;

pFile = fopen ( "test.bin" , "rb" );
if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

fseek (pFile , 0 , SEEK_END);
lSize = (ftell (pFile))/5;
rewind (pFile);

buffer = (unsigned long long*) malloc (sizeof(unsigned long long)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

result = fread (buffer,5,lSize,pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

当我输出缓冲区 [0] 时,我得到:

0100110111001110101110001110000111011111110001100011100110111011

但我想我会得到类似的东西:

0000000000000000000000001110000111011111110001100011100110111011

【问题讨论】:

  • 文件test.bin的实际内容是什么?在一些十六进制编辑器中打开它,比如 HxD(假设你在 Windows 中工作)。
  • 用零初始化缓冲区 - 例如使用calloc
  • @Dialectus 我刚刚下载了一个十六进制编辑器并检查了内容不匹配。有1011101100111001110001101101111100111001110001101101111111100001
  • “当我输出缓冲区 [0] ...”似乎没有使用标准 C 库函数。你是怎么得到这个输出的?
  • @RadLexus 我用过 cout。

标签: c


【解决方案1】:

大多数当前操作系统不允许对文件进行位访问。通过系统调用 (read()...) 或标准库函数 (getc(), fread()...) 逐字节读取文件。

为了将内容作为位来操作,您需要知道这些位是如何存储(打包)到文件字节中的。

有时位首先被打包到低位,有时首先被打包到高位,有时这种打包是基于字完成的,这增加了一层额外的复杂性,因为字可以首先存储在最低有效字节中(又名小端格式)或最高有效字节优先(又名大端格式)。

一种常见的方法是保留一个单字节缓冲区以及未读位的计数:

typedef struct bitreader {
    FILE *stream;
    int bits;
    unsigned char buffer;
} bitreader;

bitreader *bitopen(const char *filename) {
    bitreader *bp = calloc(sizeof(*bp));
    if (bp) {
        bp->stream = fopen(filename, "rb");  // open in binary mode
        if (bp->stream == NULL) {
            free(bp);
            bp = NULL;
        }
    }
    return bp;
}

void bitclose(bitreader *bp) {
    fclose(bp->stream);
    free(bp);
}

/* simplistic method to read bits packed with most significant bit first */
long long int bitread(bitreader *bp, int count) {
    long long int val = 0;
    while (count > 0) {
        if (bp->bits == 0) {
            int c = getc(bp->stream);
            if (c == EOF)
                return EOF;
            bp->buffer = c;
            bp->bits = 8;
        }
        val <<= 1;
        val |= (bp->buffer >> 7) & 1;
        bp->buffer <<= 1;
        bp->bits--;
        count--;
    }
    return val;
}

【讨论】:

  • 感谢您的回答,非常详尽。
猜你喜欢
  • 1970-01-01
  • 2010-12-08
  • 2012-03-24
  • 1970-01-01
  • 2021-04-16
  • 2013-10-17
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多