嗯,我一直在想我是否能正确处理unlink()
函数。我不希望unlink()
函数抛出一些讨厌的错误,如果它无法解除文件的链接(可能是由于文件未找到)。
我试过像
try {
unlink("secret/secret.txt");
} catch(Exception $e) {
print "whoops!";
//or even leaving it empty so nothing is displayed
}
但它不起作用。我不是PHP专家。我搜索并发现这个异常处理代码在网络的某个地方。但在我的学生时代,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)(生产和开发环境)来隐藏错误吗?
注意:这可能不再工作了。请看Brian的评论
如果你只想抑制错误,你可以这样做:
@unlink('your_file_name');
通常,在PHP中,@会抑制任何错误。
更好的方法是最小化错误概率。您说错误可能是由不存在的文件引起的。如果我是你,我会这样做:
if(file_exists('your_file_name')){
unlink('your_file_name');
}else{
echo 'file not found';
}
祝你好运:)
unlink
不抛出异常,在生成错误。正确的方法是在尝试对其调用unlink
之前检查该文件是否存在。如果您只是担心没有错误输出,那么您应该关闭display_errors
,无论如何您都应该在生产环境中这样做。然后他们就会被记录下来。
不要抑制@
的错误,这是不可取的。
我不确定你到底是什么意思。但是文档在这里。至于你为什么不想用它…这是因为你永远不会知道代码不工作或有问题。即使代码从功能的角度来看仍然可以工作,它仍然存在一个问题,这个问题可能会在某些时候使其他东西完全无法工作。如果您从未出现过错误,那么您可能会浪费大量的调试时间。你能更详细地描述一下
@
吗
更改日志级别或禁用错误显示是可以的,但你绝对不想完全抑制它们。
这个方法可能看起来很奇怪,但我相信这是最简单的方法,它解释了"竞争条件"。
- mkdir-race-condition
- file_put_contents-race-condition
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_exists。file_exists检查目录和文件,因此可能会返回具有相同文件名的目录的TRUE
,你不能使用unlink删除目录,这样做会抛出错误。
在取消链接之前检查文件是否存在(is_file)是删除文件的正确/最佳方法。
if(is_file($file) && unlink($file)){
但这不是一个万无一失的方法,因为在is_file检查和取消链接之间的小窗口中删除文件是很常见的。当一个缓存方法使用文件系统时,我已经经历过好几次了。
但这是最好的方法。
所以你可以做正确的一切,仍然得到一个错误!
好吧,至少错误告诉你如果它失败....实际上你可以在没有错误
的情况下判断它是否失败断开
成功返回
TRUE
,失败返回FALSE
。
如果你已经正确地编码了,并且可以区分成功和失败,那么是抑制错误,它对你和你的代码都没有好处。
无论错误是否被抑制,这是我能想到的防止错误发生的最好方法。通过减少检查和删除之间的时间,您将减少抛出错误的可能性。
EDIT: updated link URLs
您可以使用is_writable
来测试您是否有适当的权限来修改或删除一个文件
try {
if(!is_writable($file))
throw new Exception('File not writable');
unlink($file);
}
catch(Exception $e) { /* do what you want */ }
根据我的经验,在调用unlink()之前调用file_exists()并不工作,即使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()状态。
将unlink()错误处理为try catch
即使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;
}
=== USAGE ===
try {
if( delete_file('hello_world.xlsx') === true )
echo 'File Deleted';
}
catch (Exception $e) {
echo $e->getMessage(); // will print Exception message defined above.
}
使用PHP_Exceptionizerhttps://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操作(因此增加的处理时间可能不是什么大问题),我们调用了一个单独的内置函数(它限制了错误屏蔽问题),并且没有办法防止触发警告。如果我们能够捕获警告消息,也许我们就有了@
的合法用例:
$success = @unlink($path);
$errorInfo = error_get_last();
if ($success === false) {
$error = $errorInfo['message'] ?? 'unlink() failed';
throw new 'RuntimeException("Failed to delete file $path: $error");
}