[英]Writing a struct into a stringstream in C++
我有一些結構:
struct dHeader
{
uint8_t blockID;
uint32_t blockLen;
uint32_t bodyNum;
};
struct dBody
{
char namestr[10];
uint8_t blk_version;
uint32_t reserved1;
}
我有一個字符串流為:
std::stringstream Buffer(std::iostream::in | std::iostream::out);
我想寫一個dHdr和多個dBody結構到Buffer與
Buffer << Hdr1;
Buffer << Body1;
Buffer << Body1;
我得到錯誤:
錯誤:“緩沖區<< Hdr1”中的“ operator <<”不匹配
如果我嘗試使用:
Buffer.write(reinterpret_cast<char*>(&Hdr1), sizeof(dbHdr1));
Buffer.write(reinterpret_cast<char*>(&Body1), sizeof(Body1));
Buffer.write(reinterpret_cast<char*>(&Body2), sizeof(Body2));
我對打包和內存對齊感到困惑。
對於每個結構,您都需要定義類似於以下內容的內容:
struct dHeader
{
uint8_t blockID;
uint32_t blockLen;
uint32_t bodyNum;
};
std::ostream& operator<<(std::ostream& out, const dHeader& h)
{
return out << h.blockID << " " << h.blockLen << " " << h.bodyNum;
}
std::istream& operator>>(std::istream& in, dHeader& h) // non-const h
{
dHeader values; // use extra instance, for setting result transactionally
bool read_ok = (in >> values.blockID >> values.blockLen >> values.bodyNum);
if(read_ok /* todo: add here any validation of data in values */)
h = std::move(values);
/* note: this part is only necessary if you add extra validation above
else
in.setstate(std::ios_base::failbit); */
return in;
}
(其他結構類似)。
編輯:無緩沖的讀/寫實現具有以下缺點:
它是未格式化的; 如果您控制着小型實用程序的編譯和運行位置,那么這可能不是問題,但是通常,如果您獲取序列化數據並在不同的體系結構上運行/編譯該應用程序,則字節序會出現問題。 您還需要確保使用的類型不依賴於體系結構(即繼續使用uintXX_t
類型)。
它很脆; 實現取決於僅包含POD類型的結構。 如果稍后將char *添加到結構中,則代碼將進行相同的編譯,只顯示未定義的行為。
它是晦澀的(代碼的客戶可能希望看到為I / O定義的接口,或者假定您的結構不支持序列化)。 通常,沒有人認為“也許我可以序列化,但可以使用無緩沖的I / O”-至少在作為自定義結構或類實現的客戶端時不會。
這些問題可以得到改善,通過添加I / O流的運營商,在無緩沖讀取和寫入方面實現。
上面的運算符的示例代碼:
std::ostream& operator<<(std::ostream& out, const dHeader& h)
{
out.write(reinterpret_cast<char*>(&h), sizeof(dHeader));
return out;
}
std::istream& operator>>(std::istream& in, dHeader& h) // non-const h
{
dHeader values; // use extra instance, for setting result transactionally
bool read_ok = in.read( reinterpret_cast<char*>(&values), sizeof(dHeader) );
if(read_ok /* todo: add here any validation of data in values */)
h = std::move(values);
/* note: this part is only necessary if you add extra validation above
else
in.setstate(std::ios_base::failbit); */
return in;
}
這將代碼集中在接口后面(即,如果您的類不再支持無緩沖寫入,則您將不得不在一個位置更改代碼),並使意圖顯而易見(對結構實現序列化)。 它仍然很脆,但不那么脆弱。
您可以為std::ostream::operator<<
類似提供重載
std::ostream& operator<<(std::ostream&, const dHeader&);
std::ostream& operator<<(std::ostream&, const dBody&);
有關更多信息,請參見此stackoverflow問題 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.