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 的函数。
问题是,我想不出一种从给定文件中获取特定位的方法。
有人知道我如何获得这些信息吗?
提前致谢!
【问题讨论】:
您是要处理二进制文件(一个位表示为一个位)还是一个文本文件,其中字符0
和1
用于表示位?
创建一个小函数,从缓冲区提供 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(&bs, 3)
从文件中读取接下来的 3 位。
1如今字节几乎总是 8 位,但 C 标准仍然允许其他大小的字节,如 中的 CHAR_BIT
所指定的那样子>
【讨论】:
以上是关于C - 从二进制文件中读取位的主要内容,如果未能解决你的问题,请参考以下文章
用python从二进制文件中读取32位带符号的ieee 754浮点?