You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题根源

  1. 文件流被提前关闭:fileCopy函数末尾执行了input.close()和output.close(),但主循环还会重复调用这些已经关闭的流,导致后续读写完全失效。
  2. EOF循环写法错误:while (!input.eof())会导致最后一行被重复读取,因为eof()仅在读取失败后才会置位,而非读取到文件末尾时。
  3. 输出流重置不彻底:仅调用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;
}

额外说明

  • 如果你坚持要复用流对象,需要确保:
    1. 绝不提前关闭流;
    2. 读取前先调用input.clear()清除错误状态,再调用input.seekg(0)重置读取位置;
    3. 写入前调用output.clear()、output.seekp(0),并调用output.truncate()(C++17及以上)截断文件。
  • 但复用流对象容易因状态残留引发问题,重新打开文件的方式更可靠,尤其适合重复读写的场景。

内容的提问来源于stack exchange,提问作者Lena Abbasi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:22:02