简体   繁体   English

使用迭代器正确读取和写入std :: vector到文件中

[英]Reading and writing a std::vector into a file correctly with iterators

I'm trying to understand the answer provided here , but I can't seem to make it work. 我试图理解这里提供的答案,但我似乎无法使其发挥作用。

Here is what I've tried: 这是我尝试过的:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <fstream>

int main()
{
    std::string path("numbersfile");

    std::vector<int> myVector{1,16,32,64};
    std::vector<int> newVector{};

    std::ofstream FILE(path,std::ios::out | std::ofstream::binary);
    std::copy(myVector.begin(),myVector.end(),std::ostreambuf_iterator<char>(FILE));

    std::ifstream INFILE(path,std::ios::in | std::ifstream::binary);
    std::istreambuf_iterator<char> iter(INFILE);
    //std::copy(iter.begin(),iter.end(),std::back_inserter(newVector)); //this doesn't compile
    std::copy(iter,std::istreambuf_iterator<char>{},std::back_inserter(newVector)); // this leaves newVector empty
}

newVector is still empty after the last copy . 最后一次copy后, newVector仍为空。 How could the last statement be updated to populate newVector ? 如何更新最后一个语句以填充newVector

The file is not ready to be read by the time the second copy is called. 在调用第二个copy时,文件尚未准备好读取。 (Thanks to Piotr Skotnicki for his answer in the comments) (感谢Piotr Skotnicki在评论中的回答)

A call to flush allows the program to work: flush的调用允许程序工作:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <fstream>

int main()
{
    std::string path("numbersfile");

    std::vector<int> myVector{1,16,32,64};
    std::vector<int> newVector{};

    std::ofstream FILE(path,std::ios::out | std::ofstream::binary);
    std::copy(myVector.begin(),myVector.end(),std::ostreambuf_iterator<char>(FILE));
    FILE.flush(); // required here

    std::ifstream INFILE(path,std::ios::in | std::ifstream::binary);
    std::istreambuf_iterator<char> iter(INFILE);
    //std::copy(iter.begin(),iter.end(),std::back_inserter(newVector)); //this doesn't compile
    std::copy(iter,std::istreambuf_iterator<char>{},std::back_inserter(newVector)); // this leaves newVector empty
    return 0;
}

The ofstream is still in scope when the ifstream is created. 创建ifstream时, ofstream仍在范围内。 Had the ofstream 's destructor been called then the file would also have been ready for the ifstream . 如果已经调用了ofstream的析构函数,那么该文件也已经为ifstream做好了准备。 In the following program the ifstream is automatically destructed: 在以下程序中, ifstream会自动销毁:

#include <algorithm>
#include <fstream>
#include <iterator>
#include <vector>

std::string filename("numbersfile");

std::vector<double> myVector{1.342, 16.33, 32.1, 12364};

void write_vector_to_file(const std::vector<double>& myVector, std::string filename);
std::vector<double> read_vector_from_file(std::string filename);

int main()
{
    write_vector_to_file(myVector, filename);
    auto newVector{read_vector_from_file(filename)};
    return 0;
}

void write_vector_to_file(const std::vector<double>& myVector, std::string filename)
{
    std::ofstream ofs(filename, std::ios::out | std::ofstream::binary);
    std::ostream_iterator<double> osi{ofs," "};
    std::copy(myVector.begin(), myVector.end(), osi);
}

std::vector<double> read_vector_from_file(std::string filename)
{
    std::vector<double> newVector{};
    std::ifstream ifs(filename, std::ios::in | std::ifstream::binary);
    std::istream_iterator<double> iter{ifs};
    std::istream_iterator<double> end{};
    std::copy(iter, end, std::back_inserter(newVector));
    return newVector;
}

There are a number of flaws in your code: 您的代码中存在许多缺陷:

  1. you define a variable named FILE THIS IS BAD BAD BAD . 你定义了一个名为FILE的变量, 这是很糟糕的坏事 FILE is a name of an already existing object, it's comparable to naming an instance of a vector as: std::vector<int>array{} . FILE是已存在对象的名称,它与将vector实例命名为: std::vector<int>array{}相当。
    Not only is it confusing it's extremely dangerous as it will almost certainty lead to naming clashes. 它不仅令人困惑,而且非常危险,因为它几乎可以肯定地导致命名冲突。 Plus, all capitol names should be reserved for macros . 此外,所有国会大厦名称都应保留给宏

  2. you never check if the file is actually opened, if it isn't the compiler will not warn you and the stream will not give any indication of failure (unless explicitly checked). 你永远不会检查文件是否实际打开,如果不是,编译器不会警告你,并且流不会给出任何失败的指示(除非明确检查)。 So, you should always check. 所以,你应该经常检查。 The simplest way is too use the streams boolean operator: 最简单的方法是使用流布尔运算符:
    if (!ifile) throw std::runtime_error("error opening file");

  3. you wrote that this doesn't compile: 你写道,这不编译:

    std::copy(iter.begin(),iter.end(),std::back_inserter(newVector));

    Why would this work? 为什么会这样? Iterators themselves don't have begin and end functions, the objects associated with the iterator have those methods. 迭代器本身没有beginend函数,与迭代器关联的对象具有这些方法。

  4. Piecing all that together here is a modified version of your code: 在这里拼凑所有这些是您的代码的修改版本:

     { std::string path("numbersfile"); std::vector<int> myVector{ 1,16,32,64 }; std::vector<int> newVector{}; std::ofstream outfile(path, std::ios_base::binary); std::copy(myVector.begin(), myVector.end(), std::ostreambuf_iterator<char>(outfile)); outfile.close(); std::ifstream infile(path,std::ios_base::binary); std::istreambuf_iterator<char> iter(infile); std::copy(iter, std::istreambuf_iterator<char>(), std::back_inserter(newVector)); // this leaves newVector empty infile.close(); // close explicilty for consistency } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM