繁体   English   中英

std :: bitset的二进制序列化

[英]Binary Serialization of std::bitset

std::bitset具有to_string()用于序列作为方法char的基于字符串1秒和0秒。 显然,这对bitset中的每个位使用一个8位char ,使序列化表示比所需的时间长8倍。
我想将bitset存储在二进制表示中以节省空间。 只有当我的bitset中少于32位时, to_ulong()方法才有意义。 我有几百个。
我不确定我是否想在对象(地址)本身上使用memcpy() / std::copy() ,因为它假定对象是POD。

API似乎没有提供内部数组表示的句柄,我可以从中获取地址。

我还想选择从二进制表示中反序列化bitset。

我怎样才能做到这一点?

这是一种基于显式创建std::vector<unsigned char> ,一次读取/写入一位...

template<size_t N>
std::vector<unsigned char> bitset_to_bytes(const std::bitset<N>& bs)
{
    std::vector<unsigned char> result((N + 7) >> 3);
    for (int j=0; j<int(N); j++)
        result[j>>3] |= (bs[j] << (j & 7));
    return result;
}

template<size_t N>
std::bitset<N> bitset_from_bytes(const std::vector<unsigned char>& buf)
{
    assert(buf.size() == ((N + 7) >> 3));
    std::bitset<N> result;
    for (int j=0; j<int(N); j++)
        result[j] = ((buf[j>>3] >> (j & 7)) & 1);
    return result;
}

注意,要调用反序列化模板函数bitset_from_bytes ,必须在函数调用bitset_from_bytes大小N ,例如

std::bitset<N> bs1;
...
std::vector<unsigned char> buffer = bitset_to_bytes(bs1);
...
std::bitset<N> bs2 = bitset_from_bytes<N>(buffer);

如果你真的关心速度一个解决方案将获得一些东西将进行循环展开,以便打包例如一次完成一个字节,但更好的只是编写自己的bitset实现,不隐藏内部二进制表示而不是使用std::bitset

正如gamedev.net上的人所建议的,可以尝试使用boost :: dynamic_bitset,因为它允许访问bitpacked数据的内部表示。

编辑:以下内容无法正常工作。 显然,“二进制格式”实际上意味着“二进制的ASCII表示”。


您应该能够使用operator<<将它们写入std::ostream 在这里说:

[Bitsets]也可以直接插入并以二进制格式从流中提取。

回答我自己的问题是否完整。

显然,有这样的没有简单可移植的方法。

为了简单起见(虽然不是效率),我最终使用to_string ,然后从字符串的所有32位块(以及余数*)创建连续的32位位集,并在每个上使用to_ulong将这些位收集到二进制缓冲区。
这种方法让STL本身有点笨拙,尽管它可能不是最有效的方法。

* 请注意,由于std::bitset是在总位数上进行模板化的,因此余数位集需要使用一些简单的模板元编程算法。

除了转换为字符串并执行自己的字符串序列化之外,我看不到一种明显的方法,该字符串将8个字符的块组合成一个序列化字节。

编辑:更好的是用operator[]迭代所有位并手动序列化它。

这可能对您有所帮助,它是各种序列化类型的一个小例子。 我添加了bitset和raw位值,可以像下面这样使用。

https://github.com/goblinhack/simple-c-plus-plus-serializer上的所有示例)

class BitsetClass {
public:
    std::bitset<1> a;
    std::bitset<2> b;
    std::bitset<3> c;

    unsigned int d:1; // need c++20 for default initializers for bitfields
    unsigned int e:2;
    unsigned int f:3;
    BitsetClass(void) { d = 0; e = 0; f = 0; }

    friend std::ostream& operator<<(std::ostream &out,
                                    Bits<const class BitsetClass & > const m
    {
        out << bits(my.t.a);
        out << bits(my.t.b);
        out << bits(my.t.c);

        std::bitset<6> s(my.t.d | my.t.e << 1 | my.t.f << 3);
        out << bits(s);

        return (out);
    }

    friend std::istream& operator>>(std::istream &in,
                                    Bits<class BitsetClass &> my)
    {
        std::bitset<1> a;
        in >> bits(a);
        my.t.a = a;

        in >> bits(my.t.b);
        in >> bits(my.t.c);
        std::bitset<6> s;
        in >> bits(s);

        unsigned long raw_bits = static_cast<unsigned long>(s.to_ulong());
        my.t.d = raw_bits & 0b000001;
        my.t.e = (raw_bits & 0b000110) >> 1;
        my.t.f = (raw_bits & 0b111000) >> 3;

        return (in);
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM