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

发布于 2024-10-03 03:38:55 字数 582 浏览 8 评论 0原文

我有以下示例代码

<?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 的情况

I have the following example code

<?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");

Which creates a file, opens a pointer to it, removes the file then attempts to write to it. Now I would expect the fwrite to return false or 0 since no data will be written, however it produces the following output

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

So the fwrite apparently succeeds but the file_get_contents fails as expected.

Is it expected behaviour for the fwrite to return the number of bytes to be written? If so how can I test if the write was really successful?

This is with php 5.3.3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

少钕鈤記 2024-10-10 03:38:55

它返回 false 的原因是文件指针位于 fwrite 之后的文件末尾...这就是 fgets 应该在到达文件末尾时执行(它返回 false 因为有没有更多数据要获取)...

您需要做的是添加 fseek< /a> 在调用 fgets 之前调用:

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

编辑: 现在我理解了你的问题(并且已经查看了它):

好吧,这就是发生的事情。要理解,您必须首先了解 Linux 文件系统是如何工作的。文件名对于操作系统来说没有意义。它所做的只是指向文件的 INODE 。 inode存储数据等。它还存储硬链接 到该文件。仅当引用数降至 0 时才会删除该文件。我怀疑打开指向该文件的指针(使用 fopen 或其他系统调用)会增加引用计数。

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

所以该文件确实存在,它只是在调用 rm 后无法从文件名访问...

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

The reason it's returning false is that the file pointer is at the end of the file after fwrite... That's what fgets is supposed to do when it reaches the end of the file (it returns false since there is no more data to get)...

What you need to do is add a fseek call before you call fgets:

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

Edit: Now that I understand your question (and have looked at it):

Alright, so here's what's happening. To understand, you must first know how Linux filesystems work. The file's name is meaningless to the operating system. All it does is point to the INODE for the file. The inode stores the data, etc. It also stores a reference number to the number of hard-links to that file. The file is only deleted when the reference number falls to 0. I'm suspecting that opening a pointer to the file (using fopen, or other system calls) increases the reference count.

So basically, what that means is that when you ran rm on the file, it deleted the hard-link. But since the file was still open, you could still access the inode through fwrite (hence why the write succeeded). You couldn't access /tmp/test.txt since the hard link to that filename no longer existed. So the file became a phantom file that is only accessible by the inode. But as soon as you closed the file handle for that file (fclose, or by ending the script) the reference count fell to 0 and the inode was freed...

So the file does exist, it's just not accessible from the filename after you call rm...

That's just what I'm gathering by knowing what I know about the filesystems. I'm not saying it's 100% accurate, but it should be a decent hypothesis...

友谊不毕业 2024-10-10 03:38:55

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

这是由于硬链接的工作原理所致;文件系统中的所有条目都是硬链接、软链接或设备。

If this is on a Linux (and possible other unix-like OSes) system, the reference to the file in the filesystem is deleted by rm, but the file itself still exists until all programs reading from/writing to it are closed.

This is due to how hard links work; all entries in the filesystem are hard links, soft links, or devices.

满意归宿 2024-10-10 03:38:55

我相信你首先必须保存文件

fclose($f);

I believe you first must save the file

fclose($f);
你好,陌生人 2024-10-10 03:38:55

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

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

The following code should allow you to check whether it was a successful write.

 if (fwrite($handle, $somecontent) === FALSE) {
        echo "Cannot write to file ($filename)";
        exit;
 }
多情出卖 2024-10-10 03:38:55

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

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

Your code needs some conditions, error handling e.g.

  • check whether the file exists
  • whether the file is writable
  • whether the data was written to the file
  • whether the data are readable
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文