将“位”写入C++文件流

11 投票
7 回答
6279 浏览
提问于 2025-04-15 20:36

我该如何每次将“一位”数据写入文件流或文件结构呢?

可以先写入一个队列,然后再清空它吗?

用C#或Java可以做到吗?

这个问题是在尝试实现霍夫曼编码的时候遇到的。我不能直接把位写入文件,所以我先把它们写入一个位集合,然后在压缩完成后,每次写入其中的8位(最后一位除外)。

7 个回答

3

你在用什么文件系统呢?

大多数情况下,它会以字节为单位存储文件的长度(有没有不这样做的呢?),所以不可能有一个文件的大小不是整数个字节。

所以如果你是以比特流的方式写入文件,完成后你要么得把最后几位截断,要么就得把最后一个字节写出来,剩下的位就变成了无用的垃圾。

这里有一些Python代码可以帮助你入门

class BitFile(file):
    def __init__(self, filename, mode):
        super(BitFile, self).__init__(filename, mode)
        self.bitCount=0
        self.byte = 0

    def write(self, bit):
        self.bitCount+=1
        self.byte = self.byte*2+bit
        if self.bitCount%8==0:
            super(BitFile, self).write(chr(self.byte))
            self.byte=0

    def close(self):
        if self.bitCount%8!=0:
            super(BitFile, self).write(chr(self.byte))
        super(BitFile, self).close()     

with BitFile("bitfile.bin","w") as bf:
    bf.write(1)
    bf.write(1)
    bf.write(1)
    bf.write(0)
    bf.write(0)
    bf.write(0)
    bf.write(0)
    bf.write(0)
    bf.write(1)
8

你可以使用boost::dynamic_bitsetstd::ostream_iterator来简单地实现你想要的效果:

#include <fstream>
#include <iterator>
#include <boost/dynamic_bitset.hpp>

typedef boost::dynamic_bitset<unsigned char> Bitset;

// To help populate the bitset with literals */
Bitset& operator<<(Bitset& lhs, bool val) {lhs.push_back(val); return lhs;}

int main()
{
    Bitset bitset;
    bitset<<0<<1<<0<<1<<0<<1<<0<<1
          <<1<<0<<1<<0;

    std::ofstream os("data.dat", std::ios::binary);
    std::ostream_iterator<char> osit(os);
    boost::to_block_range(bitset, osit);

    return 0;
}

我把我的dynamic_bitset的块大小设置为8位,方法是把unsigned char作为模板参数。如果你想要更大的块大小,可以选择一个更大的整数类型。

boost::to_block_range会把位集合以块的形式输出到指定的输出迭代器。如果最后一个块里有空余的位,它们会用零来填充。

当我在十六进制编辑器中打开data.dat时,我看到的是:AA 05。这是在一个小端平台上(x64)。

13

把每一个比特(最小的信息单位)先存起来,等到凑够一个字节(8个比特)再一起处理,听起来是个不错的主意:

byte b;
int s;

void WriteBit(bool x)
{
    b |= (x ? 1 : 0) << s;
    s++;

    if (s == 8)
    {
        WriteByte(b);
        b = 0;
        s = 0;
    }
}

不过,你还得考虑一种情况,就是要写入的比特数量不是8的倍数的时候该怎么办。

撰写回答