簡體   English   中英

PHP unlink() 處理異常

[英]PHP unlink() handling the exception

好吧,我一直想知道我是否可以正確處理unlink() function。 我不希望unlink() function 如果無法取消鏈接文件(可能是由於找不到文件)拋出一些討厭的錯誤。

我嘗試了類似的東西

try { 
    unlink("secret/secret.txt"); 
} catch(Exception $e) { 
    print "whoops!"; 
    //or even leaving it empty so nothing is displayed
} 

但它不起作用。 我不是 PHP 方面的專家。 我在 web 的某處搜索並找到了這個異常處理代碼。 但我記得我的學生時代,Java 也是如此。 所以它應該工作。 我不知道代碼有什么問題。

或者我可以簡單地使用 if..else 語句,如

if(unlink($file)){
  //leaving here empty must ensure that nothing is displayed
}else{
  //leaving here empty must ensure that nothing is displayed
}

但是這段代碼也不起作用。 我在哪里做錯了? 還有什么其他方法可以正確處理它?

可以通過使用錯誤報告(PHP)(生產和開發環境)來隱藏錯誤嗎?

注意:這可能不再起作用。 見布賴恩的評論

如果你只想抑制錯誤,你可以這樣做:

@unlink('your_file_name');

通常,在 PHP 中,@ 會抑制任何錯誤。

更好的方法是最小化錯誤概率。 您已經說過錯誤可能性之一是由不存在的文件引起的。 如果我是你,我會這樣做:

if(file_exists('your_file_name')){
    unlink('your_file_name');
}else{
    echo 'file not found';
}

祝你好運 :)

unlink不會拋出異常,會產生錯誤。 正確的方法是在嘗試調用unlink之前檢查文件是否存在。 如果您只是擔心沒有錯誤輸出,那么您應該關閉display_errors ,無論如何您應該在生產環境中始終這樣做。 然后他們將被記錄。

不要用@抑制錯誤,它很少是可取的。

你能更詳細地描述@

我不確定你的意思是什么。 但是文檔在這里 至於為什么你不想使用它......那是因為你永遠不知道代碼不起作用或有問題。 即使從功能的角度來看代碼仍然有效,它仍然存在問題,並且該問題可能會使其他某些東西在某些時候完全無法工作。 如果您從未遇到過錯誤,您可能會浪費大量時間進行調試。

更改日志級別或禁用錯誤顯示很好,但您永遠不想完全抑制它們。

這種方法可能看起來很奇怪,但我相信它是最萬無一失的方法,它說明了“競爭條件”。

is_file

if(is_file($file) && @unlink($file)){
    // delete success
} else if (is_file ($file)) {
    // unlink failed.
    // you would have got an error if it wasn't suppressed
} else {
  // file doesn't exist
}

為什么?

首先is_file是檢查 FILE 是否存在而不是file_exists的正確方法。 file_exists檢查目錄和文件,因此對於具有相同文件名的目錄,可能會返回TRUE ,您不能使用unlink刪除目錄,這樣做會引發錯誤。

取消鏈接之前檢查文件是否存在( is_file )是刪除文件的正確/最佳方法。

if(is_file($file) && unlink($file)){

但這不是萬無一失的方法,因為在is_file check 和unlink之間的小窗口中刪除文件是很常見的。 當緩存方法使用文件系統時,我已經多次體驗過這種情況。

但這是最好的方法。

所以你可以做正確的一切,但仍然會出錯!

好吧,至少錯誤會告訴你它是否失敗......實際上你可以在沒有錯誤的情況下判斷它是否失敗

取消鏈接

成功時返回TRUE ,失敗時返回FALSE

如果您對它進行了正確編碼並且可以區分成功和失敗的取消鏈接,那么YES 會抑制錯誤,它不會使您或您的代碼受益。

無論錯誤是否被抑制,這是我能想到的防止它發生的最好方法。 通過減少檢查和刪除之間的時間,您將減少拋出錯誤的可能性。

編輯:更新的鏈接 URL

您可以使用is_writable來測試您是否具有修改或刪除文件的適當權限。

http://php.net/manual/en/function.is-writable.php

try {
  if(!is_writable($file))
      throw new Exception('File not writable');

  unlink($file);
}
catch(Exception $e) { /* do what you want */ }

我的經驗說,調用file_exists()只調用的unlink()之前工作,即使clearstatcache()函數被調用只調用file_exists()之前。

PHP 版本和操作系統有多種組合,我發現始終有效的唯一方法(即避免在出現錯誤時顯示警告消息)是創建我自己的函數Silent_unlink()

function silent_unlink( $filename )
{
  $old_er = error_reporting();
  error_reporting( $old_er & ~E_WARNING );
  $result = unlink( $filename );
  error_reporting( $old_er );
  return $result;
}

它禁用僅用於調用unlink()的警告錯誤報告並恢復先前的error_reporting()狀態。

使用 try catch 通過 unlink() 作為異常處理“資源不可用”錯誤

即使is_file()file_exists()也會檢查文件是否存在,有可能文件正在被某些應用程序使用,這將阻止刪除,並且unlink()將顯示“資源不可用”錯誤

因此,在嘗試了許多方法后,例如: is_resource()is_writable()stream_get_meta_data() ...等,我達到了處理錯誤的唯一最佳方法,同時“刪除”了一個不存在存在但被使用的文件一些應用

function delete_file($pFilename)
{
    if ( file_exists($pFilename) ) { 
        //  Added by muhammad.begawala@gmail.com
        //  '@' will stop displaying "Resource Unavailable" error because of file is open some where.
        //  'unlink($pFilename) !== true' will check if file is deleted successfully.
        //  Throwing exception so that we can handle error easily instead of displaying to users.
        if( @unlink($pFilename) !== true )
            throw new Exception('Could not delete file: ' . $pFilename . ' Please close all applications that are using it.');
    }   
    return true;
}

=== 用法 ===

try {
    if( delete_file('hello_world.xlsx') === true )
        echo 'File Deleted';
}
catch (Exception $e) {
    echo $e->getMessage(); // will print Exception message defined above.
}

使用 PHP_Exceptionizer https://github.com/DmitryKoterov/php_exceptionizer/blob/master/lib/PHP/Exceptionizer.php

$exceptionizer = new PHP_Exceptionizer(E_ALL);
try {
        unlink($file)
    }  catch (E_WARNING $e) {
        return false;
    }
if (file_exists($file) && is_writable($file)) {
    return  unlink($file);
}

據說錯誤抑制算子成本很高,它具有隱藏意外錯誤的潛在缺點,並且它解決的問題幾乎總是有更好的解決方案。

但是,在這種情況下,我們已經在進行重要的 I/O 操作(因此增加的處理時間可能不是什么大問題),我們正在調用一個單獨的內置 function (它限制了錯誤屏蔽問題)並且有沒有辦法阻止警告觸發。 如果我們能夠捕獲警告消息,也許我們有一個合法的@用例:

$success = @unlink($path);
$errorInfo = error_get_last();
if ($success === false) {
    $error = $errorInfo['message'] ?? 'unlink() failed';
    throw new \RuntimeException("Failed to delete file {$path}: $error");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM