C - 从二进制文件中读取位

Posted

技术标签:

【中文标题】C - 从二进制文件中读取位【英文标题】:C - reading bits from binary file 【发布时间】:2021-09-07 05:54:54 【问题描述】:

我看到了熟悉的问题,但没有任何东西可以帮助我解决问题。

假设我有一个二进制文件。 我想收集每 3 个写入位(在我们的例子中,filesize%3 == 0)并检查第 3 位是否是前两位的“|”操作的结果。 例如,如果这是我们的二进制文件: 111000101

所以我首先想得到 111,然后检查 1|1 是否为 1。 接下来,我想得到000,然后检查0|0 = 0。 最后,我想得到010,然后检查是否0|1 = 1。

现在,我一直在考虑的是创建包含 1,1,1 的 unsigned char arr[3],然后将数组发送到将检查 1|1 = 1 的函数。

问题是,我想不出一种从给定文件中获取特定位的方法。

有人知道我如何获得这些信息吗?

提前致谢!

【问题讨论】:

您是要处理二进制文件(一个位表示为一个位)还是一个文本文件,其中字符01用于表示位? 创建一个小函数,从缓冲区提供 3 位集合,该缓冲区具有 static 变量以跟踪位位置等。如果缓冲区没有足够的位,请补充并从文件缓冲区重新对齐,如果没有字节,则从文件中读取更多(或仅一个)。 继续@MikeCAT 评论,你能告诉我们打开你的文本编辑器(记事本或vim),写abc,然后保存一个文件有多少位? 如果是位级别:8 包 3 位给出 24 位,正好适合 3 个字节。因此,如果您读取文件的三个字节乘三个字节,您可以快速提取带有 AND 0x249249 的 "third" 位和带有 AND 0xDB6DB6 的 "two Significant" 位。之后,验证两个掩码是布尔数学/操作。 【参考方案1】:

C 文件 I/O(和一般的 C)是围绕 bytes1 而不是位组织的。所以通常没有办法访问文件中的特定位,只能访问字节。

因此,如果您想操作文件中的位,您需要读取包含您感兴趣的位的字节,然后提取这些位(通常使用移位和掩码)。如果你想写回这些位,你需要将它们重新打包成整个字节。

一种方法是在 C FILE * 的顶部放置一个位流抽象层,它可以从读取的每个字节中提取位(保留剩余位以供以后读取)。比如:

#include <stdio.h>
#include <limits.h>

struct bit_stream 
    FILE *fp;   // source to read from
    int byte;   // last byte read from fp
    size_t bits;   // how many bits are left in byte;
;

int read_bits(struct bit_stream *bs, size_t size) 
    if (size >= sizeof(int)*CHAR_BIT) 
        fprintf("size %z is too big\n", size);
        exit(1); 
    int rv = 0;
    size_t bits = 0;
    while (bits < size) 
        if (!bs->bits) 
            if ((bs->byte = fgetc(bs->fp)) == EOF)
                return bits ? rv : EOF;
            bs->bits = CHAR_BIT; 
        if (bs->bits > size - bits) 
            size_t extract = size - bits;
            rv |= (bs->byte & ((1U << extract) - 1)) << bits;
            bs->bits -= extract;
            bs->byte >>= extract;
            bits += extract;
         else 
            rv |= bs->byte << bits;
            bits += bs->bits;
            bs->bits = 0; 
    
    return rv;


int main() 
    struct bit_stream bs =  stdin, 0, 0 ;
    int v;
    while ((v = read_bits(&bs, 3) != EOF) 
        printf("%d\n", v);
    

这使用read_bits(&amp;bs, 3) 从文件中读取接下来的 3 位。


1如今字节几乎总是 8 位,但 C 标准仍然允许其他大小的字节,如 中的 CHAR_BIT 所指定的那样子>

【讨论】:

以上是关于C - 从二进制文件中读取位的主要内容,如果未能解决你的问题,请参考以下文章

从二进制文件中重复 fread() 16 位

用python从二进制文件中读取32位带符号的ieee 754浮点?

从二进制文件中读取并转换为双精度?

在 C++ 中写入整数并从二进制文件中读取它们:字节数 mismaych

如何从二进制文件中获取应用程序的版本号?

在python中如何从二进制文件中读取信息