ftell() 返回字节偏移量而非字符或行号,对 utf-8 文件需谨慎;追加模式下行为未定义;失败返回 false 而非 -1;最可靠用途是配合 fseek($fp, 0, seek_end) 获取文件大小。

ftell() 在 PHP 7.4 中能用,但返回值是字节偏移量,不是行号或字符数;对 UTF-8 多字节字符文件要特别小心——它不识别编码,只数字节。
ftell() 返回的是字节位置,不是字符位置
你读一个含中文的文件,fread($fp, 10) 可能只读了 3 个汉字(UTF-8 下每个汉字占 3 字节),此时 ftell($fp) 返回 10,不是 3。这个值不能直接当“第几行”或“第几个字符”用。
- 只适用于二进制安全场景,比如计算已写入多少字节、配合
fseek()做随机读写 - 文本处理中想定位到某一行?别依赖
ftell(),改用fgets()+ 计数器 - 如果文件是 ASCII 或 Latin-1 编码,字节 = 字符,这时可放心用
追加模式("a" / "a+")下 ftell() 行为不可靠
用 fopen("log.txt", "a+") 打开后立刻调 ftell($fp),PHP 7.4 返回值是未定义的(文档明确写“undefined behavior”)。不是报错,而是结果可能为 0、文件大小、甚至随机大数。
- 想获取追加模式下的真实末尾位置?先
fseek($fp, 0, SEEK_END),再ftell($fp) - 不要在
"a"模式下做fseek()后写入——写操作仍会强制追加到末尾,不管指针在哪 - 需要读写+定位?改用
"r+"或"c+"模式
ftell() 失败时返回 false,不是 -1
常见误判:把 if (ftell($fp) === -1) 当作错误判断。实际它失败时返回 false,而成功时永远返回非负整数(包括 0)。
- 正确写法:
$pos = ftell($fp); if ($pos === false) { /* handle error */ } - 注意类型严格比较:用
===,避免==把false和0混淆 - 失败通常因为句柄无效(已关闭、未成功打开)或底层系统调用失败(如 NFS 挂载异常)
配合 fseek() 计算文件大小的惯用写法
这是 ftell() 最稳定、最常用的实战场景:跳到末尾,读当前位置即得大小。
$fp = fopen("data.bin", "rb");
if ($fp === false) {
throw new RuntimeException("无法打开文件");
}
fseek($fp, 0, SEEK_END);
$size = ftell($fp); // 这里 $size 是整数,且一定有效
fclose($fp);
- 必须用
"rb"模式(二进制),避免 Windows 下"r"模式因换行符转换干扰偏移 -
SEEK_END是常量,值为 2,但写常量名更清晰、可读 - 别省略
fseek()直接ftell()——刚打开时指针在开头,返回 0
真正容易被忽略的点只有一个:ftell() 的返回值是纯字节流偏移,它对编码、换行、缓冲区一无所知。你把它当“逻辑位置”用之前,得先确认你的文件是不是单字节编码,以及你的业务是否真的只需要字节维度的定位。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











