8

我使用 Boost 将多个对象序列化为二进制存档。从 a 中读回这些对象时binary_iarchive,有没有办法知道存档中有多少对象,或者只是一种检测存档结束的方法?

我发现的唯一方法是使用 try-catch 来检测流异常。提前致谢。

4

4 回答 4

6

我可以想到几种方法:

  1. 将 STL 容器序列化到/从您的存档中(请参阅文档)。存档将自动跟踪容器中有多少对象。

  2. 在序列化对象之前序列化计数变量。在回读您的对象时,您会事先知道您希望回读多少个对象。

  3. 您可以让最后一个对象具有一个特殊值,该值充当一种指示对象列表末尾的哨兵。也许您可以isLast向对象添加成员函数。

  4. 这不是很漂亮,但是您可以在存档旁边有一个单独的“索引文件”,用于存储存档中的对象数量。

  5. 使用tellp底层流对象的位置来检测您是否在文件末尾:

示例(只是一个草图,未经测试):

std::streampos archiveOffset = stream.tellg(); 
std::streampos streamEnd = stream.seekg(0, std::ios_base::end).tellg();
stream.seekg(archiveOffset);

while (stream.tellp() < streamEnd)
{
    // Deserialize objects
}

这可能不适用于 XML 档案。

于 2011-07-13T16:15:30.907 回答
0

当您开始序列化时,您是否拥有所有对象?如果不是,那么您就是在“滥用”提升序列化 - 它不应该以这种方式使用。但是,我以这种方式使用它,try catch用于查找文件的结尾,它对我有用。只需将其隐藏在实现中的某个地方即可。但请注意,如果以这种方式使用它,您需要不序列化指针,或禁用指针跟踪。

如果您已经拥有所有对象,请参阅 Emile 的答案。它们都是有效的方法。

于 2014-03-24T09:57:16.537 回答
0
std::istream* stream_;
boost::iostreams::filtering_streambuf<boost::iostreams::input>* filtering_streambuf_;
...
stream_ = new std::istream(memoryBuffer_);
if (stream_) {
  filtering_streambuf_ = new boost::iostreams::filtering_streambuf<boost::iostreams::input>();
  if (filtering_streambuf_) {
    filtering_streambuf_->push(boost::iostreams::gzip_decompressor());
    filtering_streambuf_->push(*stream_);

    archive_ = new eos::portable_iarchive(*filtering_streambuf_);
  }
}

从档案中读取数据时使用 zip,并filtering_streambuf有这样的方法

std::streamsize std::streambuf::in_avail()
Get number of characters available to read

所以我检查存档的结尾

bool    IArchiveContainer::eof() const {
    if (filtering_streambuf_) {
        return filtering_streambuf_->in_avail() == 0;
    }
    return false;
}

知道存档中最后有多少对象无济于事,但有助于检测它们的结尾(我仅在单元测试中使用 eof 测试来对我的类/结构进行序列化/反序列化 - 以确保我我正在阅读我正在写的所有内容)

于 2019-08-29T22:51:54.947 回答
-1

您只需从文件中读取一个字节。

如果你没有到达终点,

那么 backword 一个字节。

于 2012-08-31T09:02:53.120 回答