必须用二进制模式打开文件才能用 fseek 精确字节跳转;文本模式下 fseek 偏移量不等于字节数,且仅支持 ftell 返回的合法位置;seekg 同样需注意流状态和编码影响,混用 C/C++ IO 会导致未定义行为。

c++如何修改文件指针位置_fseek与seekg偏移量计算【实战】

fseek 移动文件指针前必须确认文件是以二进制模式打开的

很多 C++ 程序员在 C 风格文件操作中踩的第一个坑是:用 fopen("data.txt", "r") 打开文本文件后调用 fseek(fp, 10, SEEK_SET),结果偏移量“不准”——尤其在 Windows 上,\r\n 被当作一个字符处理,但底层存储占两个字节,fseek 却按字节跳转,导致后续 fread 读出错乱数据。

解决方法很简单但常被忽略:

seekgstd::ifstream 中的偏移量单位始终是字节,但流状态影响实际效果

seekg 看似更“现代”,但它不是无条件生效。常见失效场景包括:

示例:安全地跳转到倒数第 10 字节

std::ifstream fin("log.dat", std::ios::binary);
fin.seekg(0, std::ios::end);
auto size = fin.tellg();
if (size > 10) {
    fin.clear(); // 清除可能的 eofbit
    fin.seekg(size - 10, std::ios::beg);
    char buf[11] = {};
    fin.read(buf, 10);
}

混合使用 fseekseekg 会导致未定义行为

C++ 标准明确禁止对同一个文件同时用 C 风格 FILE* 和 C++ 流对象操作 —— 它们各自维护独立的缓冲区和文件位置指示器。例如:

偏移量计算要区分“逻辑记录”和“物理字节”,尤其涉及结构体序列化

当你想跳到第 n 个结构体时,别直接写 fseek(fp, n * sizeof(MyStruct), SEEK_SET) —— 这假设结构体没有填充(padding),而编译器会按对齐规则插入空字节。真实布局得用 offsetofstatic_assert 验证:

真正需要随机访问的二进制数据,建议用 mmap(mmap / MapViewOfFile)替代 fseek,避免频繁系统调用和缓冲区管理负担。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。