在网站上有一个文件。 PHP脚本会像这样修改它:
$contents = file_get_contents("MyFile");
// ** Modify $contents **
// Now rewrite:
$file = fopen("MyFile","w+");
fwrite($file, $contents);
fclose($file);
修改非常简单。它抓取文件的内容并添加几行。然后它会覆盖文件。
我知道PHP有一个函数可以将内容附加到文件而不是重写它。但是,我想继续使用这种方法,因为我可能会在将来更改修改算法(所以附加可能还不够)。
无论如何,我正在测试这个,做出100个请求。每次调用脚本时,我都会在文件中添加一个新行:
第一个电话:
首先!
第二个电话:
首先!
第二!
第三个电话:
首先!
第二!
第三!
非常酷。但那时:
第四个电话:
第四!
第五个电话:
第四!
第五!
如你所见,第一,第二和第三行完全消失了。
我已经确定问题不是内容字符串修改算法(我已单独测试过它)。在读取或写入文件时,有些东西搞砸了。
我认为问题很可能是在读取文件的内容时:如果由于某些奇怪的原因$contents
为空,那么上面显示的行为是有意义的。
我不是PHP的专家,但也许我几乎同时执行100次调用的事实导致了这个问题。如果有两个进程,一个是写文件而另一个正在读取文件,该怎么办?
此问题的推荐方法是什么?当多个进程可以写/读同一个文件时,我该如何管理文件修改?
答案 0 :(得分:3)
所以问题是对同一文件的并行访问,而另一个实例在文件更新之前正在读取文件。 PHP幸运地有一个锁定文件的机制,所以在释放锁并且文件已经更新之前,没有人可以读取它。
flock()
可以使用,文档为here
答案 1 :(得分:3)
您需要做的是使用flock()
(文件锁定)
我认为正在发生的是你的脚本正在抓取文件,而前一个脚本仍在写入文件。由于文件仍然被写入,因此当PHP抓取它时它不存在,因此php获取一个空字符串,一旦后面的进程完成,它将覆盖以前的文件。
解决方案是在文件被锁定时让脚本usleep()
持续几毫秒,然后再试一次。请务必限制脚本可以尝试的次数。
<强>注意:强>
如果另一个PHP脚本或应用程序访问该文件,则可能不一定使用/检查文件锁。这是因为文件锁通常被视为可选附加项,因为在大多数情况下它们不是必需的。
答案 2 :(得分:2)
您需要创建一个锁,以便任何并发请求都必须等待轮到他们。这可以使用flock()
函数完成。您必须使用fopen()
,而不是file_get_contents()
,但这不应该是一个问题:
$file = 'file.txt';
$fh = fopen($file, 'r+');
if (flock($fh, LOCK_EX)) { // Get an exclusive lock
$data = fread($fh, filesize($file)); // Get the contents of file
// Do something with data here...
ftruncate($fh, 0); // Empty the file
fwrite($fh, $newData); // Write new data to file
fclose($fh); // Close handle and release lock
} else {
die('Unable to get a lock on file: '.$file);
}