PHP中fopen后执行rename仍读取旧文件内容的原因
问题解答:PHP读取被rename覆盖文件仍返回旧内容的原因
核心原因:Linux文件系统的inode机制
Linux类系统采用inode文件系统,文件名只是文件实际内容(inode)的一个硬链接/别名:
- 当你通过
fopen($fileA, "r")打开文件时,PHP获取的是指向该文件inode的文件描述符,这个描述符直接关联文件的实际数据块,和文件名无关。 - 执行
rename($fileB, $fileA)操作时,只是将fileA.txt这个文件名从原来的inode解绑,重新绑定到fileB.txt对应的inode上。而原来的inode因为还有你的PHP进程持有打开的文件描述符($fp未关闭),系统不会回收它,对应的旧文件内容依然存在。 - 此时调用
fread($fp),读取的是旧inode对应的内容,自然还是原文件的字符串。只有关闭$fp再重新打开,PHP才会重新解析文件名,指向新的inode,从而读取到新内容。
Windows与Linux的差异
Windows的文件系统(如NTFS)对打开的文件有严格的锁机制:当文件被进程打开时,系统会禁止其他进程对该文件执行重命名、删除等操作,所以在Windows环境下执行这段代码,rename操作会直接报错。
内容的提问来源于stack exchange,提问作者Samul
相关产品推荐
相关产品推荐

