即使文件不存在,PHP fwrite总是返回要写入的字节数,这是预期的行为吗?

时间:2010-11-18 14:13:20

标签: php fwrite

我有以下示例代码

<?php
`echo test > /tmp/test.txt`;
$f=fopen("/tmp/test.txt","w+");
`rm /tmp/test.txt`;
var_dump(fwrite($f,"test"));
fclose($f);
file_get_contents("/tmp/test.txt");

创建文件,打开指向它的指针,删除文件然后尝试写入文件。现在我希望fwrite返回false或0,因为不会写入数据,但它会产生以下输出

int(4)

Warning: file_get_contents(/tmp/test.txt): failed to open stream: No such file or directory in /Stuff/tmp/test3 on line 7

所以fwrite显然成功但是file_get_contents按预期失败。

fwrite的预期行为是否返回要写入的字节数?如果是这样,我如何测试写入是否真的成功?

这是用php 5.3.3

5 个答案:

答案 0 :(得分:5)

它返回false的原因是文件指针位于fwrite之后的文件末尾...这就是fgets到达结束时应该做的事情该文件(它返回false,因为没有更多数据可以获得)...

在致电fgets之前,您需要做的是添加fseek来电:

var_dump(fwrite($f,"test"));
fseek($f, 0);
var_dump(fgets($f));

修改:现在,我了解了您的问题(并已查看过):

好的,所以这就是发生的事情。要理解,您必须首先了解Linux文件系统的工作原理。该文件的名称对操作系统毫无意义。它只是指向文件的INODE。 inode存储数据等。它还存储对该文件的hard-links个数的引用号。只有当引用号变为0时才会删除该文件。我怀疑打开指向该文件的指针(使用fopen或其他系统调用)会增加引用计数。

基本上,这意味着当你在文件上运行rm时,它删除了硬链接。但由于文件仍处于打开状态,您仍然可以通过fwrite访问inode(因此写入成功的原因)。您无法访问/tmp/test.txt,因为该文件名的硬链接已不存在。因此该文件成为只能由inode访问的幻像文件。但是一旦你关闭了该文件的文件句柄(fclose,或者结束了脚本),引用计数就会降到0并且inode被释放......

因此文件确实存在,在您调用rm后,无法从文件名中访问...

通过了解我对文件系统的了解,这就是我正在收集的内容。我并不是说它是100%准确的,但它应该是一个不错的假设...

答案 1 :(得分:2)

如果这是在Linux(以及可能的其他类Unix操作系统)系统上,rm删除了对文件系统中文件的引用,但文件本身仍然存在,直到所有程序读取/写入关闭它。

这是由于hard links的工作方式;文件系统中的所有条目都是硬链接,soft links或设备。

答案 2 :(得分:0)

以下代码应该允许您检查它是否成功写入。

 if (fwrite($handle, $somecontent) === FALSE) {
        echo "Cannot write to file ($filename)";
        exit;
 }

答案 3 :(得分:0)

我相信你首先要保存文件

fclose($f);

答案 4 :(得分:0)

您的代码需要一些条件,例如错误处理。

  • 检查文件是否存在
  • 文件是否可写
  • 数据是否已写入文件
  • 数据是否可读