2009-01-13 113 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。

反对字符串的另一个说法是,它的名称暗示它包含一个字符串,而不是二进制缓冲区,这可能会导致读取代码的人感到困惑。

这就是说,我也推荐矢量。

相关问题