我試圖通過TCP鏈接傳送穀物的序列化結果(二進制檔案)。對於接收方來說,首先要確定需要多少字節(至少)來恢復消息對象,但似乎沒有辦法獲得這些信息。我如何知道麥片二元輸出的大小?
具有原始類型的所有成員的結構的序列化結果似乎與結構的sizeof的結果一樣大。這有什麼保證嗎?我很擔心,因爲如果使用便攜式二進制歸檔文件進行序列化,結果會增大1個字節。我知道這是記錄排列順序,但接收方怎麼知道這個?我想出的唯一安全方法是序列化消息並從輸出流中獲取大小。對於接收方來說,這看起來不太優雅。
我試圖通過TCP鏈接傳送穀物的序列化結果(二進制檔案)。對於接收方來說,首先要確定需要多少字節(至少)來恢復消息對象,但似乎沒有辦法獲得這些信息。我如何知道麥片二元輸出的大小?
具有原始類型的所有成員的結構的序列化結果似乎與結構的sizeof的結果一樣大。這有什麼保證嗎?我很擔心,因爲如果使用便攜式二進制歸檔文件進行序列化,結果會增大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()來獲得尺寸。
對於僅包含原始類型的數據結構,應該有一種方法可以在編譯時獲得序列化的大小,但是這種非最優方法只能在運行時才能得到。
這對我來說已經足夠了。
溢出的返回值可能溢出,它的一個int。我認爲mSize應該是一個int_type。 – jossgray
認爲這應該是安全的。 'int_type overflow(int_type C)override { D3UNUSED(C); if(m_size == std :: numeric_limits :: max()) return EOF; //我們會溢出失敗。 m_size ++; return 0; }' –
jossgray
更好的解決方案是重寫'xsputn'以獲得更好的性能。 – jossgray