2017-01-03 60 views
1

我試圖通過TCP鏈接傳送穀物的序列化結果(二進制檔案)。對於接收方來說,首先要確定需要多少字節(至少)來恢復消息對象,但似乎沒有辦法獲得這些信息。我如何知道麥片二元輸出的大小?

具有原始類型的所有成員的結構的序列化結果似乎與結構的sizeof的結果一樣大。這有什麼保證嗎?我很擔心,因爲如果使用便攜式二進制歸檔文件進行序列化,結果會增大1個字節。我知道這是記錄排列順序,但接收方怎麼知道這個?我想出的唯一安全方法是序列化消息並從輸出流中獲取大小。對於接收方來說,這看起來不太優雅。

回答

1

我自己找到了解決方案。在這裏共享以防其他人也有用。

獲得大小最可靠的方法是實際序列化數據,所以我做的是避免序列化過程中(當使用std :: stringstream時)通常的內存分配/訪問開銷。

該解決方案首先從STD導出:: basic_streambuf <>(對於穀物它必須是std ::流緩衝)

class COUNTER_BUFFER : public std::streambuf 
{ 
    private : 
     size_t mSize = 0; 

    private : 
     int_type overflow(int_type C) 
     { 
      return mSize++; 
     } 

    public : 
     size_t Size(void) const 
     { 
      return mSize; 
     } 
}; 

一般自std類:: basic_streambuf應的字符寫入一些緩衝區(文件,字符串等),但在這裏它計算了寫入多少個字符(字節)。

下一步指定實例爲std ::被傳遞到存檔從穀物basic_ostream:

COUNTER_BUFFER Buffer; 
std::basic_ostream<char> Stream(&Buffer); 
cereal::BinaryOutputArchive Archive(Stream); 

系列化任何數據結構正常,當它完成,調用Buffer.Size()來獲得尺寸。

對於僅包含原始類型的數據結構,應該有一種方法可以在編譯時獲得序列化的大小,但是這種非最優方法只能在運行時才能得到。

這對我來說已經足夠了。

+0

溢出的返回值可能溢出,它的一個int。我認爲mSize應該是一個int_type。 – jossgray

+0

認爲這應該是安全的。 'int_type overflow(int_type C)override { D3UNUSED(C); if(m_size == std :: numeric_limits :: max()) return EOF; //我們會溢出失敗。 m_size ++; return 0; }' – jossgray

+0

更好的解決方案是重寫'xsputn'以獲得更好的性能。 – jossgray