簡體   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