C++中重复读写同一文件遇EOF重置问题求助
文件重复读写时EOF重置失败的解决方案
问题描述
我尝试通过fstream重复读写12个文件来测量耗时并计算平均值,但在重置EOF时遇到了问题。我已经试过用clear()和seekg(0)方法,但都没用,求建议。
原代码
#define _CRT_SECURE_NO_WARNINGS #include <fstream> #include <chrono> #include <vector> #include <cstdint> #include <numeric> #include <random> #include <algorithm> #include <iostream> #include <cassert> #include <ctime> #include <cstdlib> #include <string> using namespace std; long long fileCopy(ifstream & input,ofstream & output) { char c; string line; auto startTime = std::chrono::high_resolution_clock::now(); if (input.is_open() && output.is_open()) { while (!input.eof()) { getline(input, line); output << line << endl; } } else { cout << "Unable to open input or output file\n"; } input.clear(); input.seekg(0,ios::beg); output.clear(); output.seekp( 0 ); input.close(); output.close(); auto endTime = std::chrono::high_resolution_clock::now(); return chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count(); } int main() { long long totalTime = 0.0; ifstream inputFile ("input.txt" ); ifstream inputFile1 ("input1.txt" ); ifstream inputFile2 ("input2.txt" ); ifstream inputFile3 ("input3.txt" ); ifstream inputFile4 ("input4.txt" ); ifstream inputFile5 ("input5.txt" ); ifstream inputFile6 ("input6.txt" ); ifstream inputFile7 ("input7.txt" ); ifstream inputFile8 ("input8.txt" ); ifstream inputFile9 ("input9.txt" ); ifstream inputFile10 ("input10.txt" ); ifstream inputFile11 ("input11.txt" ); ifstream inputFile12 ("input12.txt" ); ofstream outputFile("output.txt"); ofstream outputFile1("output1.txt"); ofstream outputFile2("output2.txt"); ofstream outputFile3("output3.txt"); ofstream outputFile4("output4.txt"); ofstream outputFile5("output5.txt"); ofstream outputFile6("output6.txt"); ofstream outputFile7("output7.txt"); ofstream outputFile8("output8.txt"); ofstream outputFile9("output9.txt"); ofstream outputFile10("output10.txt"); ofstream outputFile11("output11.txt"); ofstream outputFile12("output12.txt"); //1000 times doing small size read and write for (size_t i = 0; i < 1000; i++) { totalTime += fileCopy(inputFile1,outputFile1); totalTime += fileCopy(inputFile2,outputFile2); totalTime += fileCopy(inputFile3,outputFile3); totalTime += fileCopy(inputFile4,outputFile4); totalTime += fileCopy(inputFile5,outputFile5); totalTime += fileCopy(inputFile6,outputFile6); totalTime += fileCopy(inputFile7,outputFile7); totalTime += fileCopy(inputFile8,outputFile8); totalTime += fileCopy(inputFile9,outputFile9); totalTime += fileCopy(inputFile10,outputFile10); totalTime += fileCopy(inputFile11,outputFile11); totalTime += fileCopy(inputFile12,outputFile12); } //cout<< "The big file copy timing is "<< fileCopy(inputFile,outputFile) << " ms " << endl; cout<< "Total time to do 1000 times copying the 12 small files is "<< totalTime << " ms " << endl; return 0; }
问题根源
- 文件流被提前关闭:
fileCopy函数末尾执行了input.close()和output.close(),但主循环还会重复调用这些已经关闭的流,导致后续读写完全失效。 - EOF循环写法错误:
while (!input.eof())会导致最后一行被重复读取,因为eof()仅在读取失败后才会置位,而非读取到文件末尾时。 - 输出流重置不彻底:仅调用
seekp(0)只能移动写入位置,但不会清除文件原有内容,多次写入后旧内容会残留。
修复方案
核心修改点
- 每次循环重新打开文件:避免复用流对象带来的状态问题,彻底解决EOF重置失效的问题。
- 修正读取循环逻辑:改用
while (getline(input, line)),这是C++文件读取的标准正确写法。 - 输出文件每次打开时截断:用
ios::trunc标志确保每次写入从空文件开始。 - 减少不必要的缓冲区刷新:用
'\n'代替endl,避免计时误差。
修复后的代码
#define _CRT_SECURE_NO_WARNINGS #include <fstream> #include <chrono> #include <vector> #include <cstdint> #include <numeric> #include <random> #include <algorithm> #include <iostream> #include <cassert> #include <ctime> #include <cstdlib> #include <string> using namespace std; long long fileCopy(const string& inputPath, const string& outputPath) { string line; auto startTime = std::chrono::high_resolution_clock::now(); // 每次调用重新打开文件,输入流默认只读,输出流带截断标志 ifstream input(inputPath); ofstream output(outputPath, ios::trunc); if (input.is_open() && output.is_open()) { // 正确的读取循环:getline成功才执行写入 while (getline(input, line)) { output << line << '\n'; } } else { cout << "无法打开输入或输出文件: " << inputPath << " / " << outputPath << '\n'; } // 流对象销毁时自动关闭文件,无需手动调用close() auto endTime = std::chrono::high_resolution_clock::now(); return chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count(); } int main() { long long totalTime = 0; // 用vector存储文件对,简化循环代码 vector<pair<string, string>> filePairs = { {"input1.txt", "output1.txt"}, {"input2.txt", "output2.txt"}, {"input3.txt", "output3.txt"}, {"input4.txt", "output4.txt"}, {"input5.txt", "output5.txt"}, {"input6.txt", "output6.txt"}, {"input7.txt", "output7.txt"}, {"input8.txt", "output8.txt"}, {"input9.txt", "output9.txt"}, {"input10.txt", "output10.txt"}, {"input11.txt", "output11.txt"}, {"input12.txt", "output12.txt"} }; // 重复1000次复制操作 for (size_t i = 0; i < 1000; i++) { for (const auto& pair : filePairs) { totalTime += fileCopy(pair.first, pair.second); } } cout << "1000次复制12个小文件的总耗时: " << totalTime << " ms\n"; return 0; }
额外说明
- 如果你坚持要复用流对象,需要确保:
- 绝不提前关闭流;
- 读取前先调用
input.clear()清除错误状态,再调用input.seekg(0)重置读取位置; - 写入前调用
output.clear()、output.seekp(0),并调用output.truncate()(C++17及以上)截断文件。
- 但复用流对象容易因状态残留引发问题,重新打开文件的方式更可靠,尤其适合重复读写的场景。
内容的提问来源于stack exchange,提问作者Lena Abbasi
相关产品推荐
相关产品推荐

