假设我们有:文件:a.txt、b.txt和c.txtscript:script.php
我们希望允许脚本获取文件的名称(其中任何一个)、内容,然后将其删除,这样单独运行的同一脚本就不能获得同一文件。
到目前为止:
$scan = scandir('dir');
unset($scan[0], $scan[1]);
shuffle($scan);
$file = $scan[0];
$contents = file_get_contents($file);
if(unlink($file) !== false)
return $contents;
使用类似flock
的文件锁定。
我认为算法是:
- 打开文件
- 用
flock
取锁 - 检查文件是否仍然存在。如果它已经消失,转到7
- 读取文件
- 删除它
- 解锁它
- 关闭文件,忽略失败
步骤3是必需的,因为任何等待从另一个进程获取锁的进程都必然会丢失文件,因为在获取锁时该文件已被删除。
我认为在文件打开时删除它是非常安全的;只有后续的文件操作才会失败。删除被锁定的文件并没有错,因为锁与文件并没有真正的强关联,它们只是作为文件描述符表进行维护。
我认为您应该在最后关闭文件,即使它已经被删除,因为可能有操作系统资源需要清理。我不确定关闭是否会失败,但您可以简单地忽略失败(大多数人都会忽略close()
的返回值)。
另一种不必删除文件的方法是维护一个包含所有文件(文件名、读取状态)的数据库表。最初,它们都将readstatus设置为0。然后,php脚本可以从表中获取文件名,并将readstatus设置为1,这样脚本的另一个实例就不会再次获取相同的文件名。
这也会处理冲突,因为数据库会自动实现行级或表级锁定,确保脚本的两个实例不会接收到相同的文件名。