C ++:std :: ofstream方法open()在第二次迭代时擦除打开的ifstream文件

时间:2018-09-22 17:46:23

标签: c++ iteration ifstream ofstream

我正在尝试构建一个“ fileUpdater”,它将一个原始文件复制到多个目录中,以前在该目录中找到了具有相同名称和扩展名的文件。

bool update_files(const string inputPath, const vector<string> outputPaths)
{
    ifstream src(inputPath);
    if(!src.is_open())
    {
        cout << "Unable to open input file\n" << inputPath <<endl;
        return false;
    }
    else
    {
        ofstream dst;
        for(unsigned int i=0; i<= outputPaths.size()-1; i++)
        {
            dst.open(outputPaths[i]);
            try
            {
                dst << src.rdbuf();
                dst.close();
            }
            catch(int e)
            {
                cout << "Unable to replace file\n" <<endl;
                cout << outputPaths[i] <<"\n"<< endl;
                cout << "Error code: " <<e<<endl;
            }
        }
    };
    src.close();
    return true;
}

恰好在执行后

dst.open(outputPaths[i]);

在第二次迭代中,原始文件由

打开
ifstream src(inputPath);

被擦除,只有一个空文件被复制到其余目录中。 我也尝试过

dst.clear();
dst.close();

src.clear();
src.seekg(0,ios::beg);

在进入下一个迭代之前,但是没有什么区别。

更新 尝试了不同的文件后,我意识到行为取决于输入文件。 .m文件(MatLab)出现了上述行为。 使用.txt文件进行测试后,所有文件均被擦除。

2 个答案:

答案 0 :(得分:0)

所有提议的方法均无效。 既不重置指针,也不将ifstream拖入循环,这不会导致不必要地经常打开输入文件(不应更改)。

目前还不清楚,为什么dst.open(outputPaths[i]);会擦除输入文件。同样,擦除的确切时间取决于使用的文件类型。

我实施了以下解决方法,有效地将输入文件读入字符串并事先关闭它,以防止进一步的读/写操作。

bool update_files( const string inputPath, const vector<string> outputPaths)
{
    const char * in = inputPath.c_str();
    ifstream src(in);
    if(!src.is_open())
    {
        cout << "Unable to open input file\n" << inputPath <<endl;
        return false;
    }
    else
    {
        string buffer;
        streamsize s=src.gcount();
        src.seekg(0,ios::end);
        buffer.reserve(src.tellg());
        src.seekg(0,ios::beg);
        buffer.assign((istreambuf_iterator<char>(src)), istreambuf_iterator<char>());
        src.close();

        for(unsigned int i=0; i<= outputPaths.size()-1; i++)
        {
            const char * out = outputPaths[i].c_str();
            ofstream dst(out);
            try
            {
                dst << buffer;
                dst.close();
            }
            catch(int e)
            {
                cout << "Unable to replace file\n" <<endl;
                cout << outputPaths[i] <<"\n"<< endl;
                cout << "Error code: " <<e<<endl;
            }
        }
    };
    src.close();
    return true;
}

答案 1 :(得分:0)

使用dst << src.rdbuf();复制文件的方式会将当前文件位置保留在输入文件的末尾。在第二次迭代中,相同的读取将不会读取任何内容(保留文件的空副本),因为您已经位于输入文件的末尾。

解决方案是使用seekg在每次读取之前返回输入文件的开头。您应该在读取任何内容之前(打开文件后立即)致电tellg,然后搜索该位置。

auto startpos = src.tellg();
ofstream dst;
// ...
src.seekg(startpos);
dst << src.rdbuf();