2011-03-14 71 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