如何在 C++ 中逐位 read/write 位序列
how to read/write sequnce of bits bit by bit in c++
我已经在 C++ 中实现了 Huffman 编码算法,并且运行良好。我想创建一个文本压缩算法。
在数字世界的每一个文件或数据的背后,都有0/1。
我想在文件中保留由霍夫曼编码算法生成的位序列(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;
}
输出
感谢任何帮助或指向帮助的指示。谢谢。
“二进制模式”仅表示您已请求您写入的实际字节不会被行尾转换损坏。 (这只是 Windows 上的一个问题。没有其他系统需要故意破坏您的数据。)
您仍在以二进制模式一次写入一个字节。
要写入位,您需要将它们累积成一个整数。为方便起见,使用无符号整数。这是您的位缓冲区。您需要决定是从最少到最多还是从最多到最不重要的位置累积它们。一旦累积了八位或更多位,就将一个字节写入文件,并从缓冲区中删除这八位。
完成后,如果缓冲区中还有位,则将最后的一到七位写到一个字节中。你需要仔细考虑你到底是怎么做到的,以及如何知道有多少比特,这样你才能正确解码另一端的比特。
累加和提取是使用您的语言中的位运算完成的。在 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;
}
...
我已经在 C++ 中实现了 Huffman 编码算法,并且运行良好。我想创建一个文本压缩算法。
在数字世界的每一个文件或数据的背后,都有0/1。
我想在文件中保留由霍夫曼编码算法生成的位序列(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;
}
输出
感谢任何帮助或指向帮助的指示。谢谢。
“二进制模式”仅表示您已请求您写入的实际字节不会被行尾转换损坏。 (这只是 Windows 上的一个问题。没有其他系统需要故意破坏您的数据。)
您仍在以二进制模式一次写入一个字节。
要写入位,您需要将它们累积成一个整数。为方便起见,使用无符号整数。这是您的位缓冲区。您需要决定是从最少到最多还是从最多到最不重要的位置累积它们。一旦累积了八位或更多位,就将一个字节写入文件,并从缓冲区中删除这八位。
完成后,如果缓冲区中还有位,则将最后的一到七位写到一个字节中。你需要仔细考虑你到底是怎么做到的,以及如何知道有多少比特,这样你才能正确解码另一端的比特。
累加和提取是使用您的语言中的位运算完成的。在 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;
}
...