2009-01-13 40 views
44

一般來說,在C++中存儲二進制數據的最佳方式是什麼?據我所知,這些選項幾乎可以歸結爲使用字符串或向量<char> s。 (我會省略char * s和malloc()的可能性,因爲我特指C++)。用C++/STL存儲二進制數據的「正確」方法

通常我只是使用一個字符串,但是我不確定是否有我缺少的開銷,或者STL在內部執行的轉換可能會混淆二進制數據的完整性。有沒有人有這方面的指示(har)?建議或喜好的方式?

回答

38

char的向量很好,因爲內存是連續的。因此,您可以將它與許多C API一起使用,例如berkley套接字或文件API。您可以執行以下操作,例如:

std::vector<char> vect; 
    ... 
    send(sock, &vect[0], vect.size()); 

它會正常工作。

你可以像對待任何其他動態分配的字符緩衝區一樣對待它。你可以上下掃描尋找神奇的數字或模式。你可以部分解析它。對於從套接字接收,你可以很容易地調整它的大小來附加更多的數據。

缺點是調整大小不是非常有效(謹慎調整大小或預先分配),並且從數組前端刪除也將非常不夠。如果你需要,比如在數據結構的前面一次只彈出一個或兩個字符,在這個處理之前拷貝到一個deque可能是一個選項。這花費你一份副本,並且deque內存不連續,所以你不能只傳遞一個指向C API的指針。底線,瞭解數據結構及其在潛入之前的權衡,然而字符向量通常是我在一般實踐中看到的。

+2

很好的答案。對於學習部分:我發現一個不錯的圖片顯示前一段時間使用容器,並將其嵌入到此答案中:http://stackoverflow.com/questions/366432/extending-stdlist#366710 – 2009-01-13 23:20:09

6

我也使用std::string,並且從來沒有遇到過問題。

一個「指針」,我只是在一段代碼昨天收到的尖銳提醒:創建從二進制數據的一個塊字符串時,使用std::string(startIter, endIter)構造形式,而不是std::string(ptr, offset, length)形式 - 後者品牌假設指針指向一個C風格的字符串,並在第一個零字符(它複製「指定length,而不是length字符)後忽略任何內容。

+0

嗯。根據http://www.cplusplus.com/reference/string/string/string.html,std :: string(char * ptr,offset,length)ctor應該複製所有長度字節,甚至包括零字節。它是std :: string(字符串常量&,偏移量,長度)ctor,它可以複製*長度爲*的字節。 – 2009-01-14 07:20:22

3

您當然應該使用一些char的容器,但是您要使用的容器取決於您的應用程序。

Chars有幾個屬性可以使它們在保存二進制數據時很有用:標準不允許對char數據類型使用任何「填充」,這很重要,因爲這意味着您不會在二進制佈局中獲取垃圾。每個字符也保證只有一個字節,使其成爲具有設置寬度的唯一普通的舊數據類型(POD)(其他所有字符均以上限和/或下限來指定)。

關於適當的用於存儲字符的stl容器的討論在上面的Doug處理得很好。你需要哪一個完全取決於你的用例。如果你只是持有一個數據塊,沒有任何特殊的查找,追加/刪除或拼接需求,我寧願使用矢量,這使得你的意圖比std :: string更清晰,許多庫和函數會假設保存以空字符結尾的c樣式字符串。

8

std :: string的最大問題是當前標準不能保證其底層存儲是連續的。但是,沒有已知的STL實現,其中字符串不是連續的,所以在實踐中它可能不會失敗。事實上,新的C++ 0x標準將通過強制std :: string使用連續的緩衝區來解決這個問題,比如std :: vector。

反對字符串的另一個說法是,它的名稱暗示它包含一個字符串,而不是二進制緩衝區,這可能會導致讀取代碼的人感到困惑。

這就是說,我也推薦矢量。

相關問題