PHP is_readable()函数

is_readable() 函数用于检查指定的文件是否存在并且可读。这对于在尝试读取文件之前验证文件访问权限非常有用。

语法

bool is_readable ( string $filename )

参数说明

参数 描述
filename 必需。规定要检查的文件路径。

返回值

如果文件存在并且可读,返回 TRUE,否则返回 FALSE

注意:即使文件存在,如果没有适当的读取权限,is_readable()也会返回FALSE。在安全模式下,会检查UID/GID。

示例1:基本用法

检查文件是否可读:

<?php
$filename = 'config.ini';

if (is_readable($filename)) {
    echo "文件 '$filename' 可读。";

    // 尝试读取文件内容
    $content = file_get_contents($filename);
    echo "<br>文件大小: " . strlen($content) . " 字节";
} else {
    echo "文件 '$filename' 不可读或不存在。";
}
?>

示例2:检查多种文件状态

综合检查文件的多种状态:

<?php
$file = 'data.json';

echo "文件 '$file' 的状态检查:<br><br>";

if (file_exists($file)) {
    echo "✓ 文件存在<br>";

    if (is_readable($file)) {
        echo "✓ 文件可读<br>";
    } else {
        echo "✗ 文件不可读<br>";
    }

    if (is_writable($file)) {
        echo "✓ 文件可写<br>";
    } else {
        echo "✗ 文件不可写<br>";
    }

    if (is_file($file)) {
        echo "✓ 是常规文件<br>";
    }

    // 获取文件权限
    $perms = fileperms($file);
    echo "文件权限: " . substr(sprintf('%o', $perms), -4) . "<br>";
} else {
    echo "✗ 文件不存在<br>";
}
?>

示例3:批量检查文件可读性

检查多个文件的可读性:

<?php
$files = [
    'public/index.php',
    'config/database.php',
    'storage/logs/laravel.log',
    'README.md',
    'protected/.env'
];

echo "文件可读性检查报告:<br><br>";

foreach ($files as $file) {
    echo "<div class='mb-2'>";
    echo "<strong>$file</strong>: ";

    if (is_readable($file)) {
        echo "<span class='text-success'>✓ 可读</span>";

        // 显示文件信息
        if (is_file($file)) {
            $size = filesize($file);
            $modTime = date('Y-m-d H:i:s', filemtime($file));
            echo " (大小: " . number_format($size) . " 字节, 修改时间: $modTime)";
        }
    } else {
        echo "<span class='text-danger'>✗ 不可读</span>";

        if (file_exists($file)) {
            echo " - 文件存在但无法读取";
        } else {
            echo " - 文件不存在";
        }
    }

    echo "</div>";
}
?>

示例4:安全读取文件内容

在读取文件前验证可读性:

<?php
function safeReadFile($filename) {
    // 清除文件状态缓存
    clearstatcache();

    if (!is_readable($filename)) {
        return ['error' => "文件 '$filename' 不可读或不存在"];
    }

    if (!is_file($filename)) {
        return ['error' => "'$filename' 不是常规文件"];
    }

    // 检查文件大小(防止读取过大文件)
    $maxSize = 10 * 1024 * 1024; // 10MB
    $fileSize = filesize($filename);

    if ($fileSize > $maxSize) {
        return ['error' => "文件过大 ($fileSize 字节),超过限制 ($maxSize 字节)"];
    }

    // 读取文件内容
    $content = file_get_contents($filename);

    if ($content === false) {
        return ['error' => "读取文件失败"];
    }

    return [
        'success' => true,
        'content' => $content,
        'size' => $fileSize,
        'modified' => filemtime($filename)
    ];
}

// 使用示例
$result = safeReadFile('document.txt');

if (isset($result['error'])) {
    echo "错误: " . $result['error'];
} else {
    echo "文件读取成功!<br>";
    echo "大小: " . $result['size'] . " 字节<br>";
    echo "修改时间: " . date('Y-m-d H:i:s', $result['modified']) . "<br>";
    echo "内容预览: " . substr($result['content'], 0, 100) . "...";
}
?>

示例5:处理权限问题和替代方案

处理不可读文件的替代方法:

<?php
$filename = 'restricted.log';

if (is_readable($filename)) {
    // 正常读取
    $content = file_get_contents($filename);
    echo "文件内容: " . htmlspecialchars(substr($content, 0, 200));
} else {
    // 尝试其他方法
    echo "无法直接读取文件 '$filename'。尝试的解决方法:<br><br>";

    // 方法1:检查文件是否存在
    if (!file_exists($filename)) {
        echo "1. 文件不存在。<br>";
    } else {
        echo "1. 文件存在。<br>";

        // 方法2:检查文件权限
        $perms = fileperms($filename);
        $permString = substr(sprintf('%o', $perms), -4);
        echo "2. 文件权限: $permString<br>";

        // 方法3:尝试通过其他方式读取
        echo "3. 尝试其他读取方式:<br>";

        // 使用fopen测试
        $handle = @fopen($filename, 'r');
        if ($handle) {
            echo "   - fopen() 成功,文件可读<br>";
            fclose($handle);
        } else {
            echo "   - fopen() 失败: " . error_get_last()['message'] . "<br>";
        }

        // 方法4:尝试改变权限(如果可能)
        echo "4. 建议解决方案:<br>";
        echo "   - 检查文件所有者<br>";
        echo "   - 使用 chmod() 更改权限: chmod('$filename', 0644)<br>";
        echo "   - 以正确用户身份运行脚本<br>";
    }
}
?>

重要注意事项

  1. 缓存:PHP会对文件状态进行缓存,多次调用is_readable()可能返回缓存结果。使用 clearstatcache() 清除缓存。
  2. 安全模式:在安全模式下,PHP会检查当前脚本的UID/GID是否与文件匹配。
  3. 符号链接:如果参数是符号链接,is_readable()会检查链接指向的文件是否可读。
  4. 目录权限:要读取文件,需要对文件所在的所有父目录具有执行权限。
  5. SELinux/AppArmor:即使文件权限正确,SELinux或AppArmor等安全模块也可能阻止访问。
  6. 竞争条件:is_readable()检查后、实际读取前,文件状态可能发生变化。对于关键操作,应考虑异常处理。

相关函数

is_writable()

检查文件是否可写

file_exists()

检查文件或目录是否存在

is_file()

检查是否是常规文件

chmod()

改变文件权限