2011-03-09 113 views
12

std::bitset有序列化作爲1 S和0char基於字符串to_string()方法。顯然,這使用bitset中的單個8位char for 每個位,使得串行化表示比所需長8倍。
我想將二進制表示中的位集存儲起來以節省空間。只有當我的位集小於32位時,to_ulong()方法纔有意義。我有數百人。
我不確定我想在對象(地址)本身上使用memcpy()/std::copy(),因爲假定對象是POD。二進制序列化:: bitset的

該API似乎沒有提供一個句柄來處理我可以從中獲取地址的內部數組表示形式。

我也想選擇從二進制表示反序列化位集。

我該怎麼做?

+0

Big Endian或Little Endian?有很大的區別(又名排序)? – 2011-03-09 20:00:39

+4

不是。如果bitset被保存爲一個字符數組,那麼對Endianess沒有直接的影響。 – 2011-03-10 20:54:47

回答

6

這是一種基於明確創建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位集大小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

+0

+1如果廣義的工具不工作,讓你自己 – 2011-09-22 07:58:56

0

除了轉換爲字符串以外,我無法看到一種明顯的方式,並將您自己的將8個字符的塊組成字符串的字符串序列化爲單個序列化字節。

編輯:最好是迭代所有的位與operator[]並手動序列化它。

+0

我想避免手動位扭曲,因爲表示已經在內部連續數組中編碼。 – 2011-03-10 11:00:43

1

編輯:以下不按預期工作。顯然,「二進制格式」實際上是指「二進制的ASCII表示」。


您應該能夠使用operator<<,並寫入到一個std::ostream。它說here

[位集]也可以直接從二進制格式的流中插入和提取。

+0

是的,我看到這個評論。在我的bitset實現中,operator <<()只是調用to_string(),所以我不知道這意味着什麼?是否有其他一些標準參考。這可能會被提及? – 2011-03-10 20:30:29

+0

對,我剛測試過它,它也不起作用。我會更新我的答案。對不起 – user634618 2011-03-10 20:32:34

+0

是的,我只是檢查了標準,這基本上就是它說的。 – 2011-03-10 20:43:08

1

回答我自己的問題的完整性。

顯然,沒有簡單的這樣做的便攜方式。

爲簡單起見(儘管效率不高),我最終使用了to_string,然後從字符串的所有32位塊(和餘數*)中創建連續的32位位集,並在其中的每一個上使用to_ulong將這些位收集到二進制緩衝區中。
這種方法留給了STL本身,儘管它可能不是最有效的方法。

*注意,因爲std::bitset的總比特數,位集需要使用一些簡單的模板元編程算術餘模板。

+0

您的解決方案肯定比通過讀取位自己執行序列化要慢數倍... – 6502 2011-09-17 19:16:35

+0

也許吧。我必須測試一下。 – 2011-09-18 11:58:33

+0

用g ++將這些位打包成一個無符號字符數組比較慢一點,比調用'std :: bitset :: to_string'要慢一些(如果一次只需要手動展開8位,就會變得比'to_string'更快)。請注意,使用調用'to_string'後的解決方案,您仍然需要進行拆分,重新構建所有的位集,callint'to_ulong' ... – 6502 2011-09-18 13:27:06

2

正如gamedev.net上的人們所建議的,可以嘗試使用boost::dynamic_bitset,因爲它允許訪問位封裝數據的內部表示。