seekg()和seekp()分别控制读写指针,二者完全独立;必须显式分别调用,且需在二进制模式下使用、调用前clear()清状态、调用后用tellg()/tellp()验证位置。

用 seekg() 和 seekp() 控制读写位置
文件流的跳转不是靠“地址偏移”直觉操作,而是依赖两个独立指针:一个管读(istream 的 seekg()),一个管写(ostream 的 seekp())。哪怕你用 fstream 同时读写,也得分别调用——混用会失效。
常见错误是只调 seekg() 就去写,或反过来。比如打开 ios::in | ios::out 模式后,想从第 100 字节开始覆盖写入,必须先 seekp(100),否则写入仍发生在当前读位置,而非你预期的地方。
-
seekg(100)只影响下一次get()、read()等读操作 -
seekp(100)只影响下一次put()、write()等写操作 - 若需同步读写位置(如覆盖式修改),通常要连续调用两者:
file.seekg(100); file.seekp(100);
seekg() 的三个参数形式和偏移基准
跳转位置不是绝对字节号,而是“相对于某处的偏移”。seekg() 有三种调用方式,最容易错的是忽略第三个参数 dir:
-
seekg(pos):把读位置设为绝对位置pos(仅对支持随机访问的流有效,如磁盘文件;对管道/标准输入无效) -
seekg(off, dir):最常用。例如seekg(-5, ios::cur)向前回退 5 字节;seekg(0, ios::end)跳到末尾(常用来获取文件大小) -
seekg(off, ios::beg)等价于seekg(off),但显式写出更安全,避免重载歧义
注意:ios::cur 和 ios::end 在二进制模式下才可靠。文本模式下换行符处理可能让偏移量“失准”,所以涉及精确跳转务必用 ios::binary 打开文件。
立即学习“C++免费学习笔记(深入)”;
跳转后必须检查是否成功
seekg() 和 seekp() 不抛异常,失败时静默返回流对象本身,但会设置 failbit。不检查就直接读写,很可能读到空数据或写到意外位置。
- 正确做法:
if (!file.seekg(100)) { /* 处理错误 */ } - 典型失败原因:文件未打开、权限不足、跳转位置超出文件范围(如
seekg(1000, ios::beg)但文件只有 200 字节)、流已处于失效状态 - 用
file.tellg()验证跳转结果,比如seekg(0, ios::end); cout 是获取文件长度的标准方法
二进制文件跳转 vs 文本文件跳转
文本模式下,C++ 运行库可能对换行符做转换(如 Windows 的 \r\n → \n),导致 seekg() 的字节偏移与实际内容错位。所有“跳到第 N 行”或“跳到结构体第 K 个字段”类需求,都必须用二进制模式。
- 打开时加
ios::binary:fstream file("data.bin", ios::in | ios::out | ios::binary); - 结构体写入前用
pragma pack(1)避免内存填充干扰偏移计算 - 跳转到结构体数组第
i项:file.seekg(i * sizeof(MyStruct), ios::beg);
跳转本身很简单,难的是确保偏移计算和文件布局完全一致——少一个 sizeof 或多一个对齐字节,整个读写就全乱了。


















