如何在c ++中逐位读取/写入位序列

问题描述

我已经在 C++ 中实现了 Huffman 编码算法,并且运行良好。我想创建一个文本压缩算法

在数字世界的每一个文件或数据的背后,都有一个 0/​​1。

我想将 Huffman 编码算法生成的位序列 (0/1) 保留在文件中。

我的目标是保存要存储的文件中使用的位数。我将用于解码的元数据存储在单独的文件中。我想把数据一点一点的写到文件里,然后用c++一样一点一点的读取。

我在二进制模式中面临的问题是它不允许我一点一点地放置数据。 我想将“10101”一点一点地放入文件中,但它一次放入每个字符的 asci 值或 8 位。

代码

#include "iostream"
#include "fstream"
using namespace std;

int main(){
    ofstream f;
    f.open("./one.bin",ios::out | ios::binary);
    f<<"10101";
    f.close();

    return 0;
}

输出

enter image description here

感谢任何帮助或帮助指示。谢谢。

解决方法

“二进制模式”仅表示您已请求您写入的实际字节不会被行尾转换损坏。 (这只是 Windows 上的问题。没有其他系统需要故意破坏您的数据。)

您仍然以二进制模式一次写入一个字节。

要写入位,您可以将它们累加为一个整数。为方便起见,以无符号整数表示。这是您的位缓冲区。您需要决定是从最不重要的位置到最重要的位置还是从最重要的位置到最不重要的位置累积它们。一旦累积了 8 位或更多位,就将一个字节写入文件,然后从缓冲区中删除这 8 位。

完成后,如果缓冲区中还有位,则将最后一到七位写出一个字节。您需要仔细考虑您究竟是如何做到这一点的,以及如何知道有多少位,以便您可以正确解码另一端的位。

累加和提取是使用您的语言中的位操作完成的。在 C++(和许多其他语言)中,它们是 &(和)、|(或)、>>(右移)和 <<(左移)。

例如,要在缓冲区中插入一位 x,然后在 y 中插入三位,最后将最早的位放在最重要的位置:

unsigned buf = 0,bits = 0;

...

// some loop
{
   ...

   // write one bit (don't need the & if you know x is 0 or 1)
   buf = (buf << 1) | (x & 1);
   bits++;

   ...

   // write three bits
   buf = (buf << 3) | (y & 7);
   bits += 3;

   ...

   // write bytes from the buffer before it fills the integer length
   if (bits >= 8) {     // the if could be a while if expect 16 or more
       // out is an ostream -- must be in binary mode if on Windows
       bits -= 8;
       out.put(buf >> bits);
   }

   ...

}

...

// write any leftover bits (it is assumed here that bits is in 0..7 --
// if not,first repeat if or while from above to clear out bytes)
if (bits) {
    out.put(buf << (8 - bits));
    bits = 0;
}

...