2011-03-14 51 views
17

在PHP中,如何检查流资源(或文件指针,句柄或任何你想调用它们的文件)是可读或可写的?例如,如果您遇到了对资源的打开或创建情况一无所知的情况,您如何检查它是否可读?你如何检查它是否可写?如何检查PHP流资源是否可读或可写?

基于我所做的测试(仅使用PHP 5.3.3的常规文本文件),当资源不可读时,fread()不会在任何级别抛出任何错误。它只是返回一个空字符串,但它也是为一个空文件做的。理想情况下,最好有一个不会修改资源本身的检查。通过尝试读取资源来测试资源是否可读将改变指针的位置。

相反,当资源不可写入时,fwrite()不会在任何级别抛出任何错误。它只返回零。这稍微更有用,因为如果您试图将一定数量的字节写入文件并且fwrite()返回零,则说明出现了问题。但是,这仍然不是一个理想的方法,因为在我需要写入它之前知道它是否可写,而不是试图写入它并查看它是否失败会好得多。

此外,理想情况下,检查应适用于任何类型的流资源,而不仅仅是文件。

这可能吗?有这样的事吗?我一直无法找到有用的东西。预先感谢您的答案。

+0

当然,无论[' fread()'](http://php.net/fread)和['fwrite()'](http://php.net/fwrite)根据各自的文档页面返回'bool(false)'失败....但是,这不会发生在PHP 5.3.5。 – 2011-03-14 03:22:57

回答

24

很简单的魔力。只需拨打stream_get_meta_data($resource)从您的脚本,然后检查返回值的mode数组元素:

$f = fopen($file, 'r'); 
$meta = stream_get_meta_data($f); 
var_dump($meta['mode']); // r 

如果你想知道如果基础数据是可写的:

var_dump(is_writable($meta['uri'])); // true if the file/uri is writable 
+1

流可以是由fopen(),fsockopen()和pfsockopen()创建的任何流。 '用fwrite打开的任何文件都不起作用? FREAD?在某些情况下比我的解决方案更好,在其他情况下更糟糕...... **编辑**没关系,fread和fwrite使用fopen打开的USE句柄。我是个白痴。 – rockerest 2011-03-14 03:32:55

+1

@rock:你不能用'fwrite'或'fread'打开一个文件。这些功能仅适用于打开的流。该功能可用于PHP中的所有流资源。所以我没有看到它会如何变得非常糟糕。事实上,这是100%的平台独立,并且也将与流封装一起使用。所以它实际上是正确的解决方案... – ircmaxell 2011-03-14 03:35:52

+0

我想我喜欢这个。你知道手册中的['fopen()'页面的模式表(http://www.php.net/manual/en/function.fopen.php)是一个完全详尽的列表吗? – jnrbsn 2011-03-14 03:46:29

1

好的,所以这可能不是最好的解决方案,但我认为它已经足够了,因为PHP中没有任何东西可以自动执行此操作。

对于第一步,你会得到从文件资源的索引节点,然后读取的文件名:

$stat = fstat($fp); 
$inode = $stat['ino']; 
system("find -inum $inode", $result); 

直接从this question about finding the filename from a filehandle服用。

既然你有文件名(在$result)你可以做一个fileperms($result)它来获得权限。

请注意,​​返回一个int,并且该文档实现了保留该前导0(例如0755)的魔术(实际上仅仅将int视为八进制)。

还要注意的是,文件确实是INT转换成一个不错的字符串像-rw-r--r--

+0

假设资源是一个开始的文件。可以是套接字,也可以是'php:// stdin'。 – 2011-03-14 03:20:10

+0

...并且系统是* nix。这不是完美的,但我认为这是最好的PHP能做的吗? – rockerest 2011-03-14 03:21:14

+0

该文件也可能是可写的,但文件句柄仅用于阅读。尽管这很聪明。 – Charles 2011-03-14 03:26:11