提问人:M K 提问时间:11/5/2023 最后编辑:chqrlieM K 更新时间:11/6/2023 访问量:92
如何逐位读取二进制文件?
How can I read a binary file bit-by-bit?
问:
我正在做一个使用霍夫曼算法压缩/解压缩文本文件的项目。我已经成功地将给定的文本文件压缩为二进制文件 - 我已经检查了 Visual Studio 十六进制编辑器扩展,它工作正常。
但是,我真的不知道如何实现减压。我想做的是一点一点地读取二进制文件,遍历相应的霍夫曼树,并在到达叶子时写一个字符。但是,我不确定如何逐位读取二进制文件(我知道它不能直接按原样完成:当然,我必须首先进行位操作以实现压缩)。
我尝试使用该函数将位存储到缓冲区中,但坦率地说,我认为我误解了它的工作原理,我不确定要为缓冲区提供多少内存,也不确定如何从缓冲区(即数组)中检索位。fread()
char
提前感谢您的任何帮助。
答:
3赞
chqrlie
11/5/2023
#1
下面是一个使用缓冲区的简单读取包装器。它从流中逐个读取位,从第一个字节的最低有效位开始:int
// Read the next bit from the stream.
// `buffer` holds the remaining bits from the last byte read
// initial value of `buffer` should be `0`.
// Return the bit value or `EOF` at end of file
int read_next_bit(FILE *stream, int *buffer)
{
int bits = *buffer;
if (bits <= 1) {
// either no bits left or EOF reached already
if (bits == EOF) {
return EOF;
}
// get the next byte from the stream
bits = getc(stream);
if (bits == EOF) {
// if EOF, make it sticky and return it
return *buffer = EOF;
}
// set the guard bit
bits |= 0x100;
}
// shift the current bit out of the buffer
*buffer = bits >> 1;
// and return it.
return bits & 1;
}
此函数尝试最大程度地减少内存读取、写入和测试次数。
这是一种替代方法,它使用结构将比特流封装在数组中,以缓冲文件内容。
#include <stdio.h>
#include <stdbool.h>
typedef struct bitstream {
FILE *stream;
int pos, len;
unsigned char buf[BUFSIZ];
} bitstream;
#define LSB_FIRST 1
#define MSB_FIRST 2
#define BIT_ORDER LSB_FIRST // define as appropriate
// open a bitstream, return a boolean success indicator
bool bitstream_open(bitstream *bt, const char *filename) {
bt->len = bt->pos = 0;
bt->stream = fopen(filename, "rb");
return bt->stream != NULL;
}
// close a bitstream
void bitstream_close(bitstream *bt) {
if (bt->stream) {
bt->len = bt->pos = 0;
fclose(bt->stream);
bt->stream = NULL;
}
}
// read a bit from a bitstream:
// return EOF at end of file
// otherwise return the next bit
int bitstream_read(bitstream *bt) {
int pos = bt->pos;
if (pos >= bt->len) {
bt->pos = pos = 0;
bt->len = fread(bt->buf, sizeof bt->buf, bt->stream) * 8;
if (bt->len == 0)
return EOF;
}
bt->pos++;
#if BIT_ORDER == LSB_FIRST
return (buf[pos >> 3] >> (pos & 7)) & 1;
#else
return (buf[pos >> 3] >> (7 - (pos & 7))) & 1;
#endif
}
评论