seekg()和seekp()用于按字节偏移量跳转读写位置,需注意流状态、文本/二进制模式差异、双指针独立性及streamoff跨平台范围限制。

用 seekg() 和 seekp() 跳转到文件指定字节位置
在 C++ 的 std::ifstream / std::ofstream / std::fstream 中,跳转到文件某处靠的是 seekg()(get pointer)和 seekp()(put pointer)。前者管读取位置,后者管写入位置。它们不接受“行号”或“字符串匹配”,只认**字节偏移量**——也就是说,你得自己算好从哪开始数、数多少字节。
常见错误是传入负数偏移却没指定基准位置,结果指针乱跳;或者对文本文件用 seekg() 跳到中间后,紧接着调用 getline(),发现行为异常——这是因为文本模式下换行符可能被转换(如 \r\n → \n),导致字节偏移和逻辑行不一致。
-
seekg(pos):直接跳到绝对位置pos(从文件开头起算,pos类型为streampos) -
seekg(offset, dir):相对跳转,offset是streamoff类型,dir可选std::ios::beg/std::ios::cur/std::ios::end - 调用前最好检查流状态:
if (!file.good()) return;,否则跳转可能静默失败 - 二进制模式(
std::ios::binary)下偏移才可靠;文本模式下,seekg()到非起点位置后,后续读取行为标准未完全保证
为什么 seekg(100) 有时不生效?
最常踩的坑是流已处于失效(fail)或到达末尾(eof)状态。一旦发生过读取失败(比如读到文件尾、类型不匹配),failbit 或 eofbit 被置位,所有后续的 seekg() 都会被忽略——它不会报错,也不会重置状态位。
另一个容易被忽略的点:某些文件系统或底层实现对“追加模式”(std::ios::app)下的 seekp() 有特殊限制,即使你调用了,写入仍可能强制发生在文件末尾。
立即学习“C++免费学习笔记(深入)”;
- 每次
seekg()或seekp()前,先执行file.clear()清除错误标志 - 确认打开方式:需要随机访问必须用
std::ios::in | std::ios::out,且避免std::ios::app - 用
file.tellg()检查跳转后实际位置,别只信调用成功 - Windows 下用文本模式打开文件时,
seekg(5)后再get(),可能因\r\n处理导致实际读到第 6 字节的内容
fstream 同时读写时 seekg() 和 seekp() 要分开调用
同一个 std::fstream 对象维护两个独立指针:一个用于输入(get),一个用于输出(put)。你不能指望调用一次 seekg() 就让写位置也跟着动——它们互不影响。
典型场景:读取配置头(前 16 字节),然后跳回开头第 4 字节处改写一个标志位。这时必须显式调用 seekp(4),哪怕刚用 seekg(0) 回到了开头。
- 读写混合操作中,每次切换方向前,建议插入
file.sync()(如果支持)或至少一次file.flush(),避免缓冲区残留影响 - POSIX 系统上,
lseek()底层接口对单个 fd 只有一个偏移量,但 C++ 标准库通过缓冲模拟了双指针,所以行为是可移植的,但性能略低 - 若需频繁来回跳转,考虑用
std::vector<char></char>一次性读全文件再内存操作,比反复seek更快
跨平台处理大文件时注意 streamoff 的范围
streamoff 是有符号整型,其大小依赖编译器和平台。在 32 位环境下通常是 long(最大约 2GB),而 64 位下可能是 long long。如果你在 Linux 上用 g++ -m32 编译,试图 seekg(3ULL * 1024 * 1024 * 1024)(3GB),会因溢出变成负值,最终跳到奇怪位置。
更隐蔽的问题:某些老版本 libstdc++ 在 Windows MinGW 下对大于 2GB 的偏移支持不完整,tellg() 可能返回 -1 即使位置合法。
- 用
std::numeric_limits<:streamoff>::max()</:streamoff>检查当前环境上限 - 对超大文件,优先使用平台 API(如 Windows 的
SetFilePointerEx()或 POSIX 的lseek())配合fdopen()构造流,而非纯 iostream - 不要用
int或size_t存储偏移量;始终用std::streamoff接收tellg()结果
真正麻烦的不是怎么跳,而是跳完之后的状态是否可控——流标志位、缓冲区一致性、文本/二进制语义差异,这些地方一松懈,bug 就藏在看似正常的读写之间。



















