【问题标题】:Saving vector<int> to file将向量<int> 保存到文件
【发布时间】:2016-10-07 04:19:11
【问题描述】:

真的很奇怪,我在stackoverflow上没有找到这个问题的答案。

我想将std::vector&lt;int&gt; 保存到文件中。 在不同的地方我发现了以下代码:

std::vector<int> v{0,1,2,4,8,16,32,64,128,256,512};
std::ofstream outfile("test.data", std::ios::out | std::ofstream::binary);
std::copy(v.begin(), v.end(), std::ostreambuf_iterator<char>(outfile));
outfile.close();

但这里的问题是,std::ostreambuf_iterator&lt;char&gt; 在将v 的每个值写入文件之前将其转换为char。因此值256512 更改为0。生成的文件在 hexedit 下如下所示:

00000000   00 01 02 04  08 10 20 40  80 00 00

我的想法是将std::ostreambuf_iterator&lt;char&gt; 更改为std::ostreambuf_iterator&lt;int&gt;,但这不起作用。编译器抛出错误:

error: no matching function for call to ‘std::ostreambuf_iterator<int>::ostreambuf_iterator(std::ofstream&)’
std::copy(v.begin(), v.end(), std::ostreambuf_iterator<int>(outfile));

我该如何解决这个问题?

【问题讨论】:

  • #include &lt;ostream&gt;#include &lt;iterator&gt;。也可能是#include &lt;fstream&gt;
  • @Arunmu 两者都包括在内。
  • 只需删除| std::ofstream::binary。反正你也不想要二进制文件。
  • std::ostreambuf_iterator 要求模板参数为 char 类型。您可以尝试使用wchar,但对于大于65535 的值仍然会失败。为什么不使用&lt;&lt; 运算符将向量写入文件流?
  • @Alf 值仍在转换为整数。

标签: c++ c++11 serialization save


【解决方案1】:

您正在寻找std::ostream_iterator,而不是std::ostreambuf_iterator

std::vector<int> v{0,1,2,4,8,16,32,64,128,256,512};
std::ofstream outfile("test.data", std::ios::out | std::ofstream::binary);

std::copy(v.begin(), v.end(), std::ostream_iterator<int>(outfile));
outfile.close();

请注意,结果输出是:

01248163264128256512

这只是将int 向量中的值写入输出流,就像使用&lt;&lt; 运算符一样,但没有任何分隔符,这可能是也可能不是您真正想要的。但这就是它的作用。

【讨论】:

  • 是的,这是最好的方法。即使您想传递一个分隔符,如 "\n"、" "、"," 等,您也可以将其作为第二个参数传递给 std::ostream_iterator() ,它将以该格式保存。跨度>
【解决方案2】:

或者,在创建流时删除std::ofstream::binary(你也可以删除std::ios::out,因为这是ofstream的默认值)。

主要是使用std::ostream_iterator&lt;int&gt;而不是std::ostreambuf_iterator&lt;char&gt;

std::vector<int> v{0,1,2,4,8,16,32,64,128,256,512};
std::ofstream outfile("test.data");
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(outfile));
outfile.close();

您可能还想在创建ostream_iterator 时添加分隔符。

【讨论】:

    【解决方案3】:

    如果您希望将整数作为字符写入文件,那么您可以使用for_each:

    std::for_each(v.begin(), v.end(), [&outfile](int x){outfile << x;});
    

    这会将整数作为字符串写入文件的一行,它们之间没有空格,即:

    01248163264128256512

    【讨论】:

      【解决方案4】:

      您可以序列化为二进制,只要记住诸如字节顺序之类的问题就可以了。基本上,使用 std::ofstream 和 ifstream write() 和 read()。

      下面显示了序列化和反序列化的两个 progs,快速 hack,所以可能会有错误:

      #include <fstream>
      #include <stdexcept>
      #include <iostream>
      #include <vector>
      
      using std::cout;
      using std::vector;
      using std::ofstream;
      using std::ios;
      
      int main()
      {
          vector<int> datavec{0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
      
          ofstream outfile;
          outfile.open ("datafile.bin", ios::out | ios::trunc | ios::binary);
      
          for (auto val : datavec) {
              outfile.write(reinterpret_cast<const char *>(&val), sizeof(int));
              if (outfile.bad()) {
                  throw std::runtime_error("Failed to write to outfile!");
              }
          }
      
          cout << "Wrote data to file. Done.\n";
      }
      //////////////////////////////////////////////////
      
      #include <fstream>
      #include <stdexcept>
      #include <iostream>
      #include <vector>
      
      using std::cout;
      using std::vector;
      using std::ifstream;
      using std::ios;
      using std::ios_base;
      
      int main()
      {
          vector<int> datavec;
      
          ifstream infile;
          infile.open ("datafile.bin", ios::in | ios::binary);
      
          while (infile) {
              int val;
              infile.read(reinterpret_cast<char *>(&val), sizeof(int));
              if (infile.bad()) {
                  throw std::runtime_error("Failed to read from infile!");
              }
              if (infile.eof()) break;
              datavec.push_back(val);
          }
      
          cout << "Read data file. Contents of datavec: \n";
          for (auto val : datavec) {
              cout << val << ", ";
          }
          cout << "\nDone\n";
      }
      

      【讨论】:

      • 谢谢,这正是我想要的。在将读取的值推送到向量之前,我们必须创建分支if (infile.eof()) break;。否则最后读取的值会被推送两次。
      • @user38034 好点,我用您建议的附加行修改了 src 代码。
      猜你喜欢
      • 2013-02-27
      • 2018-05-18
      • 2013-02-22
      • 2012-09-04
      • 1970-01-01
      • 2012-09-21
      • 1970-01-01
      • 2018-11-23
      • 1970-01-01
      相关资源
      最近更新 更多