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

C++: std::ofstream method open() wipes open ifstream file on second iteration

我正在尝试构建一个 "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 文件测试后,所有文件都被擦除。

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

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

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

None 的建议方法有效。 既不重置指针,也不将 ifstream 拉入循环,这会导致不必要地频繁打开输入文件(不应更改)。

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

我实施了以下解决方法,有效地将输入文件读入字符串并提前关闭它,以保护它免受进一步的 read/write 操作。

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;
}