PHP文件系统操作全攻略
时间:2025-05-30 19:36:28 258浏览 收藏
本文详细探讨了PHP文件系统操作的全攻略,涵盖了文件系统的基本概念和使用方法。文章从文件系统的定义出发,深入讲解了PHP文件系统的功能,包括文件元数据获取、文件和目录的操作以及权限管理等。还介绍了面向对象的目录遍历和常用的文件系统函数库,如SplFileInfo和DirectoryIterator。此外,文中提供了多个实际操作示例,帮助读者掌握文件路径信息获取、文件类型和大小查询以及文件权限处理等技能,全面提升文件系统操作能力。
今天我们将开启一个新的探索之旅,深入了解 PHP 文件系统,系统地学习和掌握 PHP 文件系统的基本使用方法。
在日常的开发过程中,我们常常需要处理各种文件。例如,读取 .env 文件中的配置信息、将项目中的错误信息写入日志文件或者获取图片的创建时间等。在实现这些功能时,我们需要使用 PHP 文件系统接口。
以下是本文所涵盖主题的提纲:
一 什么是文件系统 二 深入 PHP 文件系统 三 面向对象的目录遍历 四 PHP 文件系统思维导图
本文篇幅较长,阅读时间约为 20 分钟,请做好准备!
一 什么是文件系统
在开始之前,我们首先需要明确我们所研究的问题领域,理解什么是文件系统,以及我们所研究的对象。
简单来说,文件系统就是管理我们的目录(文件夹)和文件的方式。通常,我们会将具有相似属性的文件存储在同一个目录中,以便后续查找。这种常见的操作就会涉及到目录和文件的管理。
对于软件工程师来说,一个典型的使用场景是在开发 MVC 项目时,将控制器、视图和模型等模块的文件存储在不同的目录结构中以便管理。
无论如何,我们根据不同特性划分文件和目录都是为了解决文件存储和查找的问题。
有了这些认知后,我们自然会想到我们当前研究的 PHP 文件系统(或文件系统)的研究对象,简单来说就是:
目录(文件夹) 文件
也就是说,本文所讲解的 PHP 文件系统函数处理,基本都是围绕目录和文件展开的。
二 深入 PHP 文件系统
在 PHP 文件系统中,内置提供了超过 80 个可用的文件系统函数。由于数量繁多且功能强大,本文无法逐一讲解所有系统函数。一方面,时间有限;另一方面,我们也没有足够的精力在短时间内掌握所有函数。
尽管如此,大家不必气馁,本文将利用有限的时间和精力,研究以下几个在文件处理时的常见话题:
文件的元数据如何获取 文件的 MIME 类型如何获取 文件和目录的操作 文件和目录的权限管理
另外,补充说明一点,PHP 标准函数库不仅为我们提供了面向过程的文件系统处理函数,同时还封装了常用目录及文件操作的面向对象接口和迭代器接口,方便大家使用:
SplFileInfo finfo DirectoryIterator RecursiveDirectoryIterator
2.1 文件系统的元数据
2.1.1 什么是元数据
元数据(meta data):通俗地说就是“数据的数据”。以一个 php 文件为例,它的元数据可以是创建时间、文件名、文件大小或文件所有权限等,这类能够表明该文件基本特征的数据就是“元数据(meta data)”。
2.1.2 常用元数据获取
在这一节,我们将学习一些经常需要获取的文件元数据函数,包括:
获取文件的最后修改时间 获取文件的上次访问时间 获取文件的路径信息 获取文件的绝对路径 获取文件类型 获取文件大小 获取文件权限 获取文件所属用户及用户组
让我们开始吧!
获取文件的最后修改时间
要获取文件的上次被修改时间戳,我们可以使用函数 filemtime($filename) 或 SplFileInfo::getMTime() 方法。
// 文件路径请求改成你自己的文件路径 $filename = "f://filesystem/test.txt"; // 面向过程: 获取文件时间 $modifyTimestamp = filemtime($filename); // 面向对象 $file = new SplFileInfo($filename); $modifyTimestamp = $file->getMTime();
获取文件的上次访问时间
可以使用函数 fileatime($filename) 或 SplFileInfo::getATime() 方法,来获取文件的最后被访问时间戳。
// 文件路径请求改成你自己的文件路径 $filename = "f://filesystem/test.txt"; // 面向过程: 获取文件时间 $accessTimestamp = fileatime($filename); // 面向对象 $file = new SplFileInfo($filename); $accessTimestamp = $file->getATime();
除了 filemtime 和 fileatime 之外,还有 filectime 来获取文件的 inode 修改时间(可认为是创建时间)。
有关时间的函数常用的就这些,为了方便记住,我们来看看它们是如何命名的:
2.1 面向过程 file 前缀,面向对象 get 前缀 2.2 a: access(访问);m:modify(修改);c:create(创建) 2.3 time 后缀 2.4 fileatime,SplFileInfo::getATime;filemtime,SplFileInfo::getMTime;filectime,SplFileInfo::getCTime。
是不是很简单呢!
3 获取文件的路径信息
除了时间这些元数据,另一个经常遇到的情况是获取文件的路径信息,包括:
3.1 目录信息
获取目录信息我们可以使用 pathinfo($filename, PATHINFO_DIRNAME)、dirname($filename) 和 SplFileInfo::getPath()。
比如下面给出的文件:
$filename = 'F:\Program Files\SSH Communications Security\SSH Secure Shell\Output.txt';
将会获取到 F:\Program Files\SSH Communications Security\SSH Secure Shell 这部分目录信息。
3.2 文件名信息
这里我们所有的文件名指的是不带扩展名后缀的文件名称,比如需要获取 your_path/filename.txt 中的 filename 部分。
需要取得文件名信息,我们可以使用 pathinfo($filename, PATHINFO_FILENAME)、basename($filename, $suffix) 和 SplFileInfo::getBasename($suffix) 获取。
这里给出的 $suffix 指不获取 $suffix 扩展名部分(比如不获取 $suffix = '.txt')。
请看下面的示例:
$filename = 'F:\Program Files\SSH Communications Security\SSH Secure Shell\Output.txt';
将会获取到 Output 这部分文件名信息。
3.3 扩展名信息
扩展名我们可以使用 pathinfo($filename, PATHINFO_EXTENSION) 和 SplFileInfo::getExtension() 方法拿到。
基于前面的了解,我们可以获取到 txt 这部分扩展信息,这里不再赘述。
3.4 basename(文件名 + 扩展名)信息
basename 指的是 文件名 + 扩展名 内容信息,可以使用 pathinfo($filename, PATHINFO_BASENAME)、 basename($filename)、SplFileInfo::getBasename() 和 SplFileInfo::getFilename() 方法拿到。
虽然这里我们列出了很多的函数,但是基本上还是比较容易理解的,需要注意的是:
pathinfo 可以获取所有文件相关的路径信息,如果指定第二个参数选项将仅获取该部分的信息 文件名和 basename 不是特别容易理解,你可以使用完全相同的方法或函数 basename 和 SplFileInfo::getBasename() 获取它们,区别在于是否摘除指定的 $suffix 后缀。
3.5 示例
getPath(); echo '--- directory begin: ---' . PHP_EOL; echo $directory1 . PHP_EOL, $directory2 . PHP_EOL, $directory3 . PHP_EOL; // 文件名 $suffix = '.txt'; $filename1 = pathinfo($filename, PATHINFO_FILENAME); $filename2 = basename($filename, $suffix); $filename3 = $file->getBasename($suffix); echo '--- filename begin: ---' . PHP_EOL; echo $filename1 . PHP_EOL, $filename2 . PHP_EOL, $filename3 . PHP_EOL; // 扩展名 $extension1 = pathinfo($filename, PATHINFO_EXTENSION); $extension2 = $file->getExtension(); echo '--- extension begin: ---' . PHP_EOL; echo $extension1 . PHP_EOL, $extension2 . PHP_EOL; // basename = 文件名 + 扩展名 $basename1 = pathinfo($filename, PATHINFO_BASENAME); $basename2 = basename($filename); $basename3 = $file->getBasename(); $basename4 = $file->getFilename(); echo '--- basename begin: ---' . PHP_EOL; echo $basename1 . PHP_EOL, $basename2 . PHP_EOL, $basename3 . PHP_EOL, $basename4 . PHP_EOL;
它们的运行结果如下:
--- directory begin: --- F:\Program Files\SSH Communications Security\SSH Secure Shell F:\Program Files\SSH Communications Security\SSH Secure Shell F:\Program Files\SSH Communications Security\SSH Secure Shell --- filename begin: --- Output Output Output --- extension begin: --- txt txt --- basename begin: --- Output.txt Output.txt Output.txt Output.txt
3.6 文件路径信息关系图
4 获取文件的绝对路径
绝对路径由 realpath($path) 和 SplFileInfo::getRealpath() 获取。
5 获取文件类型
可以使用 filetype($filename) 和 SplFileInfo::getType() 来获取文件的类型。
返回值范围:
dir file char fifo block link unknown
可以查看 Linux 文件类型与扩展名 相关文件类型,这里我们重点关注下 dir 目录和 file 普通文件类型即可。
6 获取文件大小
可以使用 filesize($filename) 和 SplFileInfo::getSize() 来获取文件的大小,不再赘述。
7 获取文件权限
可以使用 fileperms($filename) 和 SplFileInfo::getPerms() 来获取到文件的所属权限。
值得注意的是它们的返回值是十进制表示的权限,如果需要获取类似 0655 八进制权限表示法,我们需要对返回值进行处理才行:
// @see http://php.net/manual/zh/function.fileperms.php#refsect1-function.fileperms-examples $permissions = substr(sprintf("%o", fileperms($filename)), -4);
你可以通过 PHP: fileperms() values and convert these 了解更多关于 PHP 获取文件权限转换的更多细节。
基本上学习完这些文件元数据信息获取方法,差不多可以应对日常开发过程中的多数应用场景,尽管如此,还是建议仔细去阅读官方 文件系统函数,那里才是知识的源泉。
掌握文件的元数据,对我们了解文件的特性大有裨益,就好比两个人谈恋爱,懂得彼此才是最好的状态。
2.2 文件系统操作
可以说我们日常在处理文件的过程中,更多的是在操作文件或者目录(文件夹),本节我们将学习文件系统操作相关知识。
依据文件类型的不同我们可以简单的将操作分为:
对目录(dir)的操作 对普通文件(file)的操作
2.2.1 目录操作
使用场景
在处理目录时我们一般涉及如下处理:
创建目录 删除目录 打开目录 读取目录 关闭目录句柄
场景一
我们有一套 CMS 管理系统支持文件上传处理,当目录不存在时依据文件上传时间,动态的创建文件存储目录,比如,我们依据 年/月/日(2018/01/01) 格式创建目录。这里就涉及到 目录创建 的处理。
场景二
当然,文件上传完成了还不够,我们还需要读取各个目录下的所有文件。这里涉及 打开目录、读取目录 以及读取完成后 关闭目录句柄。
有了相关概念和思路后,我们具体看看究竟 PHP 文件系统给我们提供了哪些方便处理目录的函数呢?
2.2.1.1 创建目录
在 PHP 文件系统扩展中同样给我们提供了处理 目录结构的系统函数。
其中创建一个新目录需要使用 mkdir($pathname [, $mode = 0777, $recursive = false]) 函数。
$pathname 参数为待创建目录的路径 $mode 为创建目录时的访问权限,0777 意味着获取最大访问权限 $recursive 用于标识是否递归创建目录,默认 false 不会递归创建
请看一个示例:
$pathname = "/path/to/your/upload/file/2018/01/01"; $created = mkdir($pathname);
创建目录是不是特别的简单呢?
但是等等,我们在类 Unix 系统中满心欢喜的使用 mkdir 并采用 $mode=0777 权限来创建一个全新的目录,但为什么当我们进入到目录中看到的目录的权限却是 0755 呢?
umask 掩码
这里涉及到 umask 掩码的问题!
重点: 原来我们在类 Unix 系统中创建新目录是给出的权限会默认减去当前系统的 umask 值,才是实际创建目录时的所属权限。
什么意思呢?
比如:
// 我们期望创建的文件权限 $mode = 0777; // 当前系统中 umask 值 $umask = 0022; // 可以由 umask 命令查看当前系统 umask 值,默认是 0022 // 实际创建的文件权限 0777 - 0022 = 0755
现在我们来对之前的实例稍作修改,看看 PHP 如何创建目录时得到希望的系统权限吧:
$pathname = "/path/to/your/upload/file/2018/01/01"; // 将系统 umask 设置为 0,并取得当前 umask 值(比如默认 0022) $umask = umask(0); $created = mkdir($pathname, $mode = 0777); // 将系统 umask 设置回原值 umask($umask);
有关 umask 函数说明可以查看官方手册。另外可以查看 Why can't PHP create a directory with 777 permissions? 这个问答了解更多细节。
2.2.1.2 目录遍历
面向过程的目录遍历提供两种解决方案:
通过 opendir、readdir 和 closedir 来遍历目录; 另一种是直接使用 scandir 遍历指定路径中的文件和目录。
目录遍历示例一,出自 官方文档:
目录遍历示例二,出自 官方文档:
. // [1] => .. // [2] => bar.php // [3] => foo.txt // [4] => somedir // )
目录的操作处理大致就是在处理这两类问题,相比于普通文件的处理来讲简单很多,下一节我们会学习有关普通文件的处理,请大家做好战斗准备。
2.2.2 文件操作
使用场景
可以说我们在处理文件系统时,绝大多数都是在处理一个普通文件,那么我们在操作文件时,我们究竟在做什么呢?
你可能已经想到了,没错我们多数时候就是在处理如下文件问题:
创建一个新的空文件 打开一个文件句柄,以供后续读取或写入 将文件中的内容覆盖掉(覆盖写入),或者在文件末尾写入新的内容(追加写入) 读取文件的内容 删除文件 复制文件 关闭文件句柄
文件的读取和写入相对会复杂一些,所以这两部分的内容会在稍后详细讲解。先让我们看看其它几个常见文件处理。
2.2.2.1 创建空文件
创建空文件有两种方式: 一是:以写入(w)模式使用 fopen($filename, $mode = 'wb') 打开一个文件,当文件不存在时则会创建一个新文件; 二是:使用 touch 函数创建一个新文件。
这两个函数同其它文件系统函数使用大致相同,感兴趣的朋友可以阅读手册,这里不作展开。
2.2.2.2 删除文件
删除文件由 unlink($filename) 函数完成。
2.2.2.3 复制文件
复制文件由 copy($source, $dest) 函数完成,会将 $source 文件拷贝到 $dest 文件中。
如果需要移动文件(重命名)可以使用 rename($oldname, $newname) 完成这个处理。
本篇关于《PHP文件系统操作全攻略》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于文章的相关知识,请关注golang学习网公众号!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
465 收藏
-
115 收藏
-
275 收藏
-
181 收藏
-
307 收藏
-
470 收藏
-
486 收藏
-
469 收藏
-
201 收藏
-
340 收藏
-
398 收藏
-
480 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习