检查文件指针在PHP中是否仍然有效

时间:2012-11-19 09:09:11

标签: php fopen fwrite unlink file-pointer

如果您使用简单的fopen / fwrite(),例如:

$ref = @fopen('/path/to/file', 'x+b'); // returns false if already exists
if ($ref) {
    fwrite($ref, 'A');
    sleep(5);
    fwrite($ref, 'B');
}

如果其他进程在睡眠期间删除文件,如何检查文件指针是否仍然有效?

我考虑过使用一个简单的is_file()检查,但是这不会说另一个进程是否确实unlink()然后创建了一个具有相同路径的新文件。

作为参考,fwrite似乎仍然返回true,即使文件已经unlink()'ed。

编辑:为了澄清,睡眠(5)只是一个随机时间,在竞争条件下可能只有几毫秒。

4 个答案:

答案 0 :(得分:3)

我刚刚做了一个测试,似乎fstat是解决方案:

$fd = fopen("/path/to/file", "w");
var_dump(fstat($fd)); // shows ['nlink'] => int(1)
sleep(60);
// in a shell console, remove the file
var_dump(fstat($fd)); // shows ['nlink'] => int(0)

答案 1 :(得分:2)

您需要再次执行fopen()。在linux系统上,你可以写入已删除的文件,因为你仍然引用它。当你关闭它时,文件最终会被删除。

如果进程需要等待,我会关闭,然后在睡眠之间打开文件

答案 2 :(得分:2)

如果你拿着文件的句柄,你不需要打扰它。文件系统正在处理这个问题。

修改

句柄有效,除非您关闭它或脚本结束并且删除文件与句柄的有效性完全无关,因此锁定。人们可以通过创建大文件(1GB)并开始使用浏览器获取来轻松检查,现在您可以“安全地”从其他进程中删除它。即使像ls这样的工具不再将文件列为现有文件,这也不会影响提取。我写“安全”,因为如果下载失败,那么httpd将关闭打开的句柄然后,如果没有其他进程持有句柄,它将phisicaly释放磁盘空间。但它 DOES 只要至少有一个引用它,数据仍保留在磁盘上(可以通过使用df等工具检查可用磁盘空间来轻松检查 - 顺序:< / p>

create 1GB file
df
start download
rm file
df

第二个df将指示discspace与第一个相同(假设当然没有发生其他文件操作)。现在停止下载并再次执行df。现在可用空间为1GB。

请注意,Windows的FS不会让您删除已打开的文件,但这只是实施而非技术限制。 * nix上的大多数(如果不是每个)FS都会毫无问题地处理这个问题。

答案 3 :(得分:0)

只是添加了许多精度:fopen()锁定取决于您打开文件的类型。 ww+会锁定 - rar+不会(默认情况下)。但是,如果您确实希望确保您的文件无法在其他地方使用,则函数flock()可能会派上用场。

但是,如果你确实需要锁定文件并在5秒内不对其进行任何操作,我会反而质疑你的设计/实现,而不是找到解决方法。