PHP 中的文件读写与上传
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($filesas$file){if($file!='.'&&$file!='..'){// 判断是文件还是目录$type=is_file($dir.'/'.$file)?'文件':'目录';echo$type.":".$file."<br>";}}?>RecursiveDirectoryIterator(递归遍历,适合多层目录)
<?php$dir='./uploads';// 使用递归迭代器$iterator=newRecursiveIteratorIterator(newRecursiveDirectoryIterator($dir,RecursiveDirectoryIterator::SKIP_DOTS),RecursiveIteratorIterator::SELF_FIRST);foreach($iteratoras$file){// $file 是 SplFileInfo 对象echo"路径:".$file->getPathname()." - 大小:".$file->getSize()." 字节<br>";}?>文件上传 :图片上传
文件上传是 Web 开发的经典需求,PHP 通过$_FILES超全局变量和move_uploaded_file()函数处理。
<formaction="upload.php"method="post"enctype="multipart/form-data">选择图片:<inputtype="file"name="avatar"accept="image/*"><inputtype="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('文件移动失败');}?>