您的位置:首页 >C++如何用fseek和seekg定位文件指针
发布于2026-04-08 阅读(0)
扫一扫,手机访问
必须用二进制模式打开文件才能用 fseek 精确字节跳转;文本模式下 fseek 偏移量不等于字节数,且仅支持 ftell 返回的合法位置;seekg 同样需注意流状态和编码影响,混用 C/C++ IO 会导致未定义行为。

fseek 移动文件指针前必须确认文件是以二进制模式打开的很多 C++ 程序员在 C 风格文件操作中踩的第一个坑是:用 fopen("data.txt", "r") 打开文本文件后调用 fseek(fp, 10, SEEK_SET),结果偏移量“不准”——尤其在 Windows 上,\r\n 被当作一个字符处理,但底层存储占两个字节,fseek 却按字节跳转,导致后续 fread 读出错乱数据。
解决方法很简单但常被忽略:
"r", "w")下,fseek 的偏移量单位是“文件位置”,不等于字节数,且只允许跳转到 ftell 返回过的合法位置(比如不能随意跳到中间某字节)fopen("data.bin", "rb") 或 "wb"seekg 在 std::ifstream 中的偏移量单位始终是字节,但流状态影响实际效果seekg 看似更“现代”,但它不是无条件生效。常见失效场景包括:
failbit 或 eofbit 状态(比如之前读到了文件末尾),此时 seekg 调用会静默失败 —— 必须先调用 clear()seekg(pos, std::ios::beg) 时,pos 是从文件开头算的字节偏移,和 fseek(fp, pos, SEEK_SET) 行为一致seekg(0, std::ios::end) 后再 tellg() 得到的是文件总字节数,这在文本文件中才真正可靠;若中间有宽字符或 BOM,需注意编码(如 UTF-8 下 BOM 占 3 字节)示例:安全地跳转到倒数第 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);
}
fseek 和 seekg 会导致未定义行为C++ 标准明确禁止对同一个文件同时用 C 风格 FILE* 和 C++ 流对象操作 —— 它们各自维护独立的缓冲区和文件位置指示器。例如:
fopen 打开文件并 fseek 到中间,再用该文件名构造 std::ifstream,后者初始位置仍是文件开头,不是 fseek 的位置seekg 移动,再用 fileno() 拿到 fd 去 lseek,C++ 流内部缓存可能还没刷新,读写会错位std::filebuf::fdopen(C++17 起)显式绑定同一底层句柄,并确保同步刷新当你想跳到第 n 个结构体时,别直接写 fseek(fp, n * sizeof(MyStruct), SEEK_SET) —— 这假设结构体没有填充(padding),而编译器会按对齐规则插入空字节。真实布局得用 offsetof 或 static_assert 验证:
#pragma pack(1) 强制紧凑排列(适合跨平台二进制协议),但会牺牲访问性能fread(&s, 1, sizeof(s), fp)std::string),绝对不能直接 fseek + fread —— 它们内存布局不可序列化真正需要随机访问的二进制数据,建议用 mmap(mmap / MapViewOfFile)替代 fseek,避免频繁系统调用和缓冲区管理负担。
上一篇:Steam家庭共享设置教程详解
下一篇:家具ERP借出明细怎么查?
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9