PHP文件覆写时的内容状态及并发读取结果技术问询
关于PHP文件覆写的两个问题解答
1. 在PHP中覆写文件内容的过程中,文件内会包含什么内容?
这个得看你用的具体覆写手段,以及操作系统的文件系统特性,常见两种情况:
- 要是用常规截断式覆写(比如用
fopen($file, 'w')打开文件,或者直接调用file_put_contents($file, $newContent)默认模式),操作系统会先把原文件的内容清空(文件大小直接变成0),之后再把新内容逐步写进去。所以在这个过程中,文件的中间状态要么是空的,要么是写了一部分的新内容——取决于你是一次性写完还是分批次写入。 - 要是用原子替换式覆写(比如先写临时文件,写完后用
rename()替换原文件,或者file_put_contents配合锁+临时文件的逻辑),那原文件会一直保持完整的旧内容,直到新文件完全写入完成,才会被原子性地替换掉。这种情况下,覆写过程中原文件的内容根本不会变,只有替换完成后才会变成新内容。
2. 若使用大内容覆写文件,当其他主体在覆写过程中拉取文件内容时,会获取到原内容、无内容还是其他结果?
答案还是得看覆写方式,两种情况差异很大:
- 用普通的截断后逐步写入(比如直接用
w模式打开后分多次fwrite大内容):- 如果刚好在截断完成但还没开始写入的时候读取,拿到的就是空内容;
- 如果在写入进行中读取,拿到的是部分写入的新内容——也就是已经写进去多少,就读到多少,大概率是残缺的;
- 只有等写入完全结束后,才能拿到完整的新内容。
- 用原子化的覆写方式(比如先写临时文件,写完再rename替换):
- 在临时文件写入的整个过程中,其他主体读取原文件时,拿到的还是完整的原内容;
- 只有当
rename()操作完成的那一刻,读取才会切换到新内容。因为rename在绝大多数Unix-like系统和Windows上都是原子操作,不会出现半新半旧的中间状态。
要是你想避免其他读取者拿到残缺内容的情况,强烈建议用原子写入的方式,举个简单的实现例子:
// 创建临时文件 $tempFile = tempnam(sys_get_temp_dir(), 'file_replace'); // 把大内容写入临时文件 file_put_contents($tempFile, $largeContent); // 原子替换目标文件 rename($tempFile, $targetFile);
这样就能保证读取者要么拿到完整的旧文件,要么拿到完整的新文件,不会碰到中间的尴尬状态。
内容的提问来源于stack exchange,提问作者Arșavin
相关产品推荐
相关产品推荐

