【问题标题】:How to dump std::vector<bool> in a binary file?如何将 std::vector<bool> 转储到二进制文件中?
【发布时间】:2015-04-14 09:19:52
【问题描述】:

我编写工具来转储和加载二进制文件中的常见对象。在第一个快速实现中,我为std::vector&lt;bool&gt; 编写了以下代码。它可以工作,但显然没有在内存中进行优化。

template <>
void binary_write(std::ofstream& fout, const std::vector<bool>& x)
{
    std::size_t n = x.size();
    fout.write((const char*)&n, sizeof(std::size_t));
    for(std::size_t i = 0; i < n; ++i)
    {
        bool xati = x.at(i);
        binary_write(fout, xati);
    }
}

template <>
void binary_read(std::ifstream& fin, std::vector<bool>& x)
{
    std::size_t n;
    fin.read((char*)&n, sizeof(std::size_t));
    x.resize(n);
    for(std::size_t i = 0; i < n; ++i)
    {
        bool xati;
        binary_read(fin, xati);
        x.at(i) = xati;
    }
}

如何在我的信息流中复制std::vector&lt;bool&gt; 的内存?

注意: 我不想替换 std::vector&lt;bool&gt; 其他东西。

【问题讨论】:

  • 即使你已经在代码的其他地方使用了std::vector&lt;bool&gt;,我强烈建议你改用std::bitsetboost::dynamic_bitset 并使用他们的to_string 功能,或者他们的ostream operator&lt;&lt; 的重载。
  • to_string 用于二进制存储?真的吗 ? ^^
  • 对,这不是我最聪明的评论;)。尽管如此,在查找 std::bitset 的功能之后,这似乎是唯一的方法(bitset->string->某种整数)。那,或者一个一个地获取位。我很好奇哪个会更快......嗯,再想一想,坚持std::vector&lt;bool&gt;(参见例如this question
  • 使数据持久化是序列化程序的工作。不需要手工制作。
  • @Klaus:编写一个有特定需求的序列化程序是我的工作。我不需要判断问题的相关性。我需要解决方案。 ;-)

标签: c++ boolean stdvector


【解决方案1】:

回答我自己的问题,目前已被验证为最佳答案,但如果有人提供更好的答案,它可能会改变。

一种方法如下。它需要访问每个值,但它可以工作。

template <>
void binary_write(std::ofstream& fout, const std::vector<bool>& x)
{
    std::vector<bool>::size_type n = x.size();
    fout.write((const char*)&n, sizeof(std::vector<bool>::size_type));
    for(std::vector<bool>::size_type i = 0; i < n;)
    {
        unsigned char aggr = 0;
        for(unsigned char mask = 1; mask > 0 && i < n; ++i, mask <<= 1)
            if(x.at(i))
                aggr |= mask;
        fout.write((const char*)&aggr, sizeof(unsigned char));
    }
}

template <>
void binary_read(std::ifstream& fin, std::vector<bool>& x)
{
    std::vector<bool>::size_type n;
    fin.read((char*)&n, sizeof(std::vector<bool>::size_type));
    x.resize(n);
    for(std::vector<bool>::size_type i = 0; i < n;)
    {
        unsigned char aggr;
        fin.read((char*)&aggr, sizeof(unsigned char));
        for(unsigned char mask = 1; mask > 0 && i < n; ++i, mask <<= 1)
            x.at(i) = aggr & mask;
    }
}

【讨论】:

  • 这样写大小不安全。此外,vector 的大小是 std::vector::size_type 不一定与 unsigned int 相同。
  • 你说得对,但现有向量的大小似乎不可能溢出unsigned long int,因为unsigned long int &gt;= void* &gt;= size of the RAM &gt;= size of the vector。在这种特定情况下,对位进行计数,然后元素的数量可能大于 RAM,但模板约束让我们认为它是用于所有向量的相同整数类型。在我的例子中,size_type 是一个 size_t,它是一个 64 位的 uint,与 unsigned long int 相同。该错误只会发生在具有非常大的布尔向量的假设编译器中。
  • 我根据您的评论修改了答案。我讨厌在影响超出范围的代码时使用大小类型(例如,当与来自用户的数据相关时),因为对于开发人员来说管理变得非常不清楚。但这里不是这样。
【解决方案2】:

很抱歉,但答案是您不能以便携方式执行此操作。

要以不可移植的方式执行此操作,您可以为 vector&lt;bool&gt; 编写一个特定于您的标准库实现的迭代器的函数。

如果幸运的话,相关字段将在迭代器中公开,因此您不必将私有更改为公开。

【讨论】:

  • 实际上,我可以通过在 1 个字节中聚合 8 个值来实现这一点,并将这个字节存储在我的文件中。但我更喜欢一个不错的解决方案。 :-)
  • @Caduchon:不过,您必须单独访问向量的位。我的意思是你无法避免这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 2017-08-28
相关资源
最近更新 更多