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;
}
我正在尝试构建一个 "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;
}