tellg返回输入流中get指针从文件开头起算的当前位置(字节数),类型为streampos;仅对输入流有效,需二进制模式打开文件并配合seekg(0,ios::end)才能准确获取文件大小。

tellg 返回的是输入流中“get 指针”的当前位置
这个位置是从文件开头起算的字节数,类型是 streampos(通常可当 long 用,但不保证是 int 或 size_t)。它只对输入流(std::istream、std::ifstream、std::fstream)有效。
常见误用场景:
- 在未打开文件或打开失败后直接调用
tellg(),返回值是streampos(-1)(即无效位置),但不会报错,容易被忽略 - 用文本模式打开文件时,
tellg()的返回值可能和实际字节数不一致(因换行符转换:Windows 下\r\n被读作一个\n,但磁盘上占 2 字节) - 调用
tellg()前没做任何读操作,指针默认在开头,返回 0 —— 这本身没错,但容易误以为“已定位到有效数据处”
tellp 返回的是输出流中“put 指针”的当前位置
同样以字节为单位,从文件开头起算,类型也是 streampos。它只对输出流(std::ostream、std::ofstream、std::fstream)有效。
关键注意点:
-
tellp()在只写模式(ios::out)下,刚打开文件时返回 0;但如果用ios::app打开,指针会自动跳到文件末尾,此时tellp()返回的就是文件长度 - 对同一个
std::fstream对象,若同时用于读写,tellg()和tellp()可能返回不同值 —— 它们是两个独立指针,不是“同一个位置的两种叫法” - 用
seekp()移动写指针后写入数据,会覆盖而非插入;tellp()返回的就是覆盖起点,不是插入点
为什么不能混用 tellg 和 tellp?
因为底层语义完全不同:
-
tellg()是“下一次get()或read()会从哪读” -
tellp()是“下一次put()或write()会往哪写” - 哪怕你用
std::fstream同时打开读写,也不能假设tellg() == tellp()—— 尤其在执行过read()但没seekp()的情况下,两个指针早已分道扬镳 - 标准不保证二者在任意时刻可比;强行比较可能掩盖逻辑错误,比如误以为“刚读完的位置就是接下来该写的位置”,而实际上写操作可能触发缓冲区刷新、隐式 seek 等行为
获取文件长度时 tellg 的典型用法与陷阱
最常见用途是计算文件大小,但必须严格按顺序操作:
- 用二进制模式打开:
std::ifstream fs("a.bin", std::ios::binary)—— 文本模式下结果不可靠 - 先
fs.seekg(0, std::ios::end),再fs.tellg(),这才是文件总字节数 - 别省略
seekg(0, std::ios::end)直接调tellg(),否则返回的是初始位置(0) - 如果文件为空,
tellg()返回 0,这是正确结果,不是错误 - 调用
tellg()后记得检查流状态:if (fs.fail()) { /* handle error */ },因为 seek 可能失败(如文件被其他进程锁住)
实际中最容易被忽略的,是文本模式与二进制模式下 tellg 行为的差异 —— 它不只影响精度,还可能导致跨平台读写错位。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











