PHP 中的文件读写与上传
判断与信息获取
判断文件
| 函数 | 说明 | 返回值 |
|---|---|---|
file_exists($path) | 判断文件或目录是否存在 | bool |
is_file($path) | 判断是否是文件 | bool |
is_dir($path) | 判断是否是目录 | bool |
is_readable($path) | 判断是否可读 | bool |
is_writable($path) | 判断是否可写 | bool |
<?php
$file = './config.php';
$dir = './logs';
// 1. 判断文件是否存在
if (file_exists($file)) {
echo "文件存在<br>";
// 2. 判断是否是文件
if (is_file($file)) {
echo "这是一个文件<br>";
}
}
// 3. 判断目录是否存在且可写
if (is_dir($dir) && is_writable($dir)) {
echo "目录存在且可写<br>";
}
?>
获取文件信息
| 函数 | 说明 |
|---|---|
filesize($path) | 获取文件大小(字节) |
filemtime($path) | 获取文件最后修改时间(时间戳) |
pathinfo($path) | 获取文件路径信息(目录、文件名、后缀) |
<?php
$file = './photo.jpg';
// 获取文件大小
$size = filesize($file);
echo "文件大小:" . round($size / 1024, 2) . " KB<br>";
// 获取最后修改时间
$mtime = filemtime($file);
echo "最后修改时间:" . date('Y-m-d H:i:s', $mtime) . "<br>";
// 获取路径信息
$info = pathinfo($file);
echo "文件名:" . $info['filename'] . "<br>";
echo "后缀名:" . $info['extension'] . "<br>";
echo "目录:" . $info['dirname'] . "<br>";
?>
文件读写
简单方式:file_get_contents() / file_put_contents()
// 读取文件内容到字符串
$content = file_get_contents(string $filename);
// 将字符串写入文件(返回写入的字节数)
file_put_contents(string $filename, mixed $data, int $flags = 0);
读取 JSON 配置文件
<?php
// 假设 config.json 内容:{"db_host": "localhost", "db_user": "root"}
$json = file_get_contents('./config.json');
$config = json_decode($json, true); // 转数组
echo "数据库主机:" . $config['db_host']; // 数据库主机:localhost
?>
写入日志文件(追加模式)
<?php
// 日志内容
$log = "[".date('Y-m-d H:i:s')."] 用户登录成功\n";
// FILE_APPEND:追加写入(不覆盖原内容)
// LOCK_EX:独占锁(防止多人同时写入导致数据混乱)
file_put_contents('./logs/app.log', $log, FILE_APPEND | LOCK_EX);
?>
底层方式:fopen() / fwrite() / fclose()
当你需要逐行读取、写入大文件或更精细的控制时,使用这组函数。
// 打开文件,返回资源句柄
$handle = fopen(string $filename, string $mode);
// 写入文件
fwrite(resource $handle, string $data);
// 读取一行
$line = fgets(resource $handle);
// 关闭文件
fclose(resource $handle);
常用 mode 参数
| 模式 | 说明 |
|---|---|
r | 只读,指针在开头 |
w | 只写,清空文件内容,指针在开头 |
a | 追加,指针在末尾 |
r+ | 读写,指针在开头 |
逐行读取大文件(不占内存)
<?php
// 打开一个大文件(比如 1GB 的日志)
$handle = fopen('./large_file.log', 'r');
if ($handle) {
// 逐行读取,直到文件结束
while (($line = fgets($handle)) !== false) {
// 处理每一行(比如过滤错误日志)
if (strpos($line, 'ERROR') !== false) {
echo "发现错误:" . $line . "<br>";
}
}
fclose($handle);
}
?>
目录操作:创建、删除与遍历
| 函数 | 说明 |
|---|---|
mkdir($path) | 创建目录 |
rmdir($path) | 删除空目录 |
unlink($path) | 删除文件 |
递归创建多级目录
<?php
// 要创建的目录路径
$dir = './uploads/2023/10/01';
// mkdir 第三个参数 true:递归创建父目录
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
echo "目录创建成功";
}
?>
遍历目录
scandir()(简单遍历,适合单层目录)
<?php
$dir = './uploads';
// 获取目录下所有文件和目录(包含 . 和 ..)
$files = scandir($dir);
// 遍历并过滤掉 . 和 ..
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
// 判断是文件还是目录
$type = is_file($dir . '/' . $file) ? '文件' : '目录';
echo $type . ":" . $file . "<br>";
}
}
?>
RecursiveDirectoryIterator(递归遍历,适合多层目录)
<?php
$dir = './uploads';
// 使用递归迭代器
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
// $file 是 SplFileInfo 对象
echo "路径:" . $file->getPathname() . " - 大小:" . $file->getSize() . " 字节<br>";
}
?>
文件上传 :图片上传
文件上传是 Web 开发的经典需求,PHP 通过 $_FILES 超全局变量和 move_uploaded_file() 函数处理。
<form action="upload.php" method="post" enctype="multipart/form-data">
选择图片:<input type="file" name="avatar" accept="image/*">
<input type="submit" value="上传">
</form>
<?php
// 检查是否有上传错误
if ($_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
exit('上传错误:' . $_FILES['avatar']['error']);
}
// 定义上传目录
$uploadDir = './uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
// 获取文件后缀,生成唯一文件名
$ext = pathinfo($_FILES['avatar']['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $ext;
$destPath = $uploadDir . $filename;
// 验证文件类型(简单验证:只允许图片)
$allowedTypes = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array(strtolower($ext), $allowedTypes)) {
exit('只允许上传图片文件');
}
// 验证文件大小(限制 2MB)
if ($_FILES['avatar']['size'] > 2 * 1024 * 1024) {
exit('文件大小不能超过 2MB');
}
// 从临时目录移动到目标目录
if (move_uploaded_file($_FILES['avatar']['tmp_name'], $destPath)) {
echo "上传成功!文件路径:" . $destPath;
} else {
exit('文件移动失败');
}
?>