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

使用C++打印文件最后N行时遭遇fseek异常问题求助

问题:读取文件最后N行时首行首字符丢失的原因分析

代码实现

用户编写的C++代码用于提取输入文件的最后N行并写入输出文件:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void printLastNLines(const std::string& inputFileName, const std::string& outputFileName, int N);
int main()
{
    printLastNLines("test.csv", "test2.csv", 200);

}
void printLastNLines(const std::string& inputFileName, const std::string& outputFileName, int N) {
    FILE* in, * out;
    int count = 0;
    long int pos;
    char s[100];

    fopen_s(&in, inputFileName.c_str(), "rb");
    /* always check return of fopen */
    if (in == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }
    fopen_s(&out, outputFileName.c_str(), "wb");
    if (out == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }
    
    
    fseek(in, 0, SEEK_END);
    pos = ftell(in);
    
    while (pos) {
        pos--;
        fseek(in, pos, SEEK_SET); 
        char c = fgetc(in);
        if (c == '\n') {
            if (count++ == N) break;
        }
    }
    //fseek(in, pos, SEEK_SET);
    /* Write line by line, is faster than fputc for each char */
    while (fgets(s, sizeof(s), in) != NULL) {
        fprintf(out, "%s", s);
    }
    fclose(in);
    fclose(out);
}

测试情况

  • 测试文件test.csv内容:
2
3
  • 运行代码后,输出文件test2.csv仅包含:
3
  • 更大文件测试时,提取的首行第一个字符总是丢失;取消注释代码中的fseek(in, pos, SEEK_SET);后问题解决。

原因分析

问题的核心是**fgetc会自动推进文件指针**,导致循环结束后文件指针的位置与你预期的pos不一致:

  1. 循环中每次执行fseek(in, pos, SEEK_SET);后,文件指针定位到pos位置;
  2. 调用fgetc(in)读取该位置的字符时,文件指针会自动向后移动1个字节,指向pos+1的位置;
  3. 循环结束后,你误以为文件指针停留在pos位置,但实际上它已经在pos+1处;此时直接调用fgets,会从pos+1开始读取,自然跳过了pos位置的字符——也就是你丢失的首行第一个字符。

以你的测试文件为例:
文件字节布局为'2' '\n' '3' '\n',总长度4。循环结束时pos=0,但经过最后一次fgetc读取'2'后,文件指针已经移动到1的位置。此时fgets从1开始读取,拿到的内容是"\n3\n",写入后就只剩"3\n"。

取消注释fseek(in, pos, SEEK_SET);后,会将文件指针重新定位到pos位置,确保fgets从正确的起始点开始读取,从而避免丢失字符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:17:50