这次我们来学习的是一些不是太常用,但却也非常有用的一些函数。它们中有些大家可能见过或者使用过,有一些可能就真的没什么印象了。它们都是 PHP 中文件系统相关操作函数的一部分。存在即合理,或许只是我们的业务开发中还没有接触到而已。不管别的,先混个脸熟,在真正需要它们的时候你能马上想起来 PHP 就自带一个这样的函数就可以了。

目录判断、创建、删除、路径缓存信息

var_dump(is_dir("./")); // bool(true)
var_dump(disk_free_space("./")); // float(7727517696)
var_dump(disk_total_space("./")); // float(250790436864)

is_dir() 函数估计大家会比较常用,就是用来判断给定的路径是否存在或者是否正常。一般在手动创建目录之前都会使用这个函数来判断一下目录是否已经创建过了,常见于上传相关的业务场景开发中。disk_free_space() 和 disk_total_space() 则是获取指定目录的剩余磁盘空间和总的磁盘空间数据的函数。因为我的电脑是 Mac 系统,所以总的磁盘空间就是 250G 的,可用的空间为 7G ,看来马上就要准备清理一下电脑了。

var_dump(mkdir("./a")); // bool(true)
var_dump(rmdir("./a")); // bool(true)

mkdir() 函数用于创建一个目录,它除了给定的路径参数外,还有一个可选参数可以设置目录的文件权限,也是传递 0777 之类的值就可以了,这个函数相信大家不会很陌生,大部分的文件上传分目录的能力正是使用 is_dir() 来配合 mkdir() 进行目录创建的。rmdir() 是用于删除目录的,这个函数有两个前提,一是要删除的目录必须是空的,二是要有删除这个目录的权限,如果任一条件不满足的话,就会报出一个 E_WARNING 级别的错误。

realpath('./');
var_dump(realpath_cache_get());
// array(8) {
// ["/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source"]=>
// array(4) {
// ["key"]=>
// float(1.4990943845035E+19)
// ["is_dir"]=>
// bool(true)
// ["realpath"]=>
// string(61) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source"
// ["expires"]=>
// int(1603327834)
// }
// ["/Users/zhangyue/MyDoc/博客文章"]=>
// array(4) {
// ["key"]=>
// int(8597410586338680)
// ["is_dir"]=>
// bool(true)
// ["realpath"]=>
// string(34) "/Users/zhangyue/MyDoc/博客文章"
// ["expires"]=>
// int(1603327834)
// }
// ["/Users"]=>
// ……
// …… var_dump(realpath_cache_size()); // int(673)

realpath_cache_get() 函数用于获取真实目录缓存的详情,我们需要先使用 realpath() 获得一个目录路径,然后就可以看到 realpath_cache_get() 里面的内容。可以看出它返回的数组中,是这条路径从第一个目录到这个目录中的所有目录信息,包括每一级目录的 realpath 、 is_dir 等属性信息。realpath_cache_size() 获取的是真实路径缓冲区的大小,也就是真实路径缓存区大小在内存中的使用量。

软连接信息

上篇文章中我们已经学过了如何创建连接文件,这次我们再来看看两个小的关于连接信息的函数。

var_dump(readlink('ltest2.txt')); // "test.txt"
var_dump(is_link('ltest2.txt')); // bool(true)

readlink() 函数用于获得软连接所连接到的真实文件的名称。在上篇文章中,我们创建的 ltest2.txt 文件正是 test.txt 文件的软连接。而 is_link() 函数则用于判断给定的文件是否是一个连接文件。

拷贝、移动、改名、删除文件操作

var_dump(copy('test.txt', 'cp_test.txt')); // bool(true)

var_dump(is_file("cp_test.txt")); // bool(true)

var_dump(move_uploaded_file('test.txt', 'mv_upload_test.txt')); // bool(false)
var_dump(is_file("mv_upload_test.txt")); // bool(false)
var_dump(is_uploaded_file("mv_upload_test.txt")); // bool(false) var_dump(copy('test.txt', 're_test.txt')); // bool(true)
var_dump(rename('re_test.txt', 'new_re_test.txt')); // bool(true) var_dump(copy('test.txt', 'del_test.txt')); // bool(true)
var_dump(unlink("del_test.txt")); // bool(true)

对于文件来说,copy() 是非常常用的一个函数。不管是写代码还是日常办公,复制粘贴这样的拷贝操作都是我们工作中的重心所在。PHP 提供的 copy() 函数就是专门用于文件拷贝的,不过需要注意的是,一定要有文件和拷贝目标目录的读写权限哦。

move_uploaded_file() 文件相信大家也是非常熟悉的,在上传文件的操作中也是经常会用到的一个功能。不过需要注意的是,从文件名就可以看出,move_uploaded_file() 的作用是移动已上传文件,也就是 $_FILES 里面 tmp 中的文件,它是不能当做 copy() 函数来使用的。从演示代码中就可以看出,对于普通文件来说,它是无法拷贝移动的。is_uploaded_file() 函数就是用于判断要操作的文件是不是一个 PHP 已上传文件。

通过上面这两个函数,相信不少人都会想到文件上传中他们的使用,这里就给出一个简单的伪代码。

if(!move_uploaded_file('xxxx', 'xxxx')){
if(copy('xxxx', 'xxxx')){
// 上传成功
}else{
// 上传失败
}
}

很多教程里都会有这样的写法,甚至一些框架中也会有这样的写法。其实就是先使用 move_uploaded_file() 去移动上传文件,如果失败了,再使用 copy() 函数拷贝一次。如果还是失败了,就认为整个上传操作失败了。

rename() 函数用于给文件改名,其实它就是类似于 Linux 系统中的 mv 命令。

is_file() 函数用于判断给定的文件是否是一个正常的文件。在操作系统中,特别是 Linux 系统中,一切皆文件,所以这个函数真正最常用的场景是判断给定的路径到底是目录还是一个文件,很多时候我们会用它来判断上传成功后的文件是否正常,或者判断一个给定的路径到底是一个目录还是一个文件。

最后就是 unlink() 函数。在 PHP 中,没有 delete 或者 rm 这样的函数,unlink() 就是用于删除文件的。不过它的名字起得却像是要解除符号连接文件的连接一样,不管是连接文件还是普通文件,都是通过这个 unlink() 函数来进行删除的。

文件一次性读取

关于文件一次性读取到内容和流式按字节或行来读取的内容我们之前已经有一篇文章详细的学习讲解过,大家可以移步 PHP大文件读取操作 中查看。所以这里我们就简单的贴出代码演示一下。

var_dump(file_exists('test.txt')); // bool(true)
var_dump(readfile('test.txt')); // asdfasdfint(8)
var_dump(file('test.txt'));
// array(1) {
// [0]=>
// string(8) "asdfasdf"
// } $c = file_get_contents('test.txt');
var_dump($c); // string(8) "asdfasdf" var_dump(file_put_contents('fpc_test.txt', $c)); // int(8)

file_exists() 函数是专业的用于判断文件是否存在的函数,上面的 is_file() 会更多地用于上传之后的操作。而 file_exists() 则是在日常的代码编写中非常常用的函数。readfile() 直接读取文件内容到内容中,file_get_contents() 也是这样的功能,只不过 file_get_contents() 返回的是以字符串为格式的文件内容。注意看我们 var_dump() 的结果,file_get_contents() 明显的标了是 string(8) 这样的类型,而 readfile() 是直接输出内容,不走缓冲区的,也就是说它是类似于 phpinfo() 这样的函数。需要使用 ob_start() 之类的函数才能将 readfile() 函数读取的内容放到一个变量中,我们之前的文章也专门讲过缓冲区的概念,PHP中的输出缓冲控制 。它的返回值是文件的字节数,也就是后面的 int(8) 。

file() 函数是将文件的内容保存到一个数组中,它会默认以行进行分隔,也就是每一行分为数组中的一个元素。

file_put_contents() 是将给定的内容写入到一个文件中,和 file_get_contents() 配合也可以实现一个拷贝的操作。

文件属性

var_dump(fileatime('test.txt')); // int(1603243708)
var_dump(filectime('test.txt')); // int(1603242166)
var_dump(filemtime('test.txt')); // int(1603242166) var_dump(fileinode('test.txt')); // int(8707958352)
var_dump(filesize('test.txt')); // int(8)
var_dump(filetype('test.txt')); // string(4) "file" var_dump(is_executable('test.txt')); // bool(true)
var_dump(is_writable('test.txt')); // bool(true)
var_dump(is_readable('test.txt')); // bool(true)

很明显,fileatime() 、filectime() 、filemtime() 对应的就是文件的上次访问时间、inode修改时间以及修改时间,和 Linux 系统中的文件相关的那三个时间概念一致。fileinode() 用于获得文件的 inode 信息。filesize() 就是文件的大小,filetype() 是文件的类型信息。

is_executable() 用于判断文件是否可以执行,is_writable() 、is_readable() 判断文件是否可以写和读。这三个函数对应的就是文件的权限相关的判断。

创建不重名文件及临时文件

var_dump(tempnam('./', 't_')); // string(70) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source/t_Gx6S5d"

$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
// sleep(30); // /tmp/phpU2LZ3V 文件
echo fread($temp, 1024), PHP_EOL; // writing to tempfile
fclose($temp); // 文件直接被删除了

tempnam() 函数会根据指定的 prefix 参数来生成一个随机不重名的空文件。在测试代码中,我们给定的 prefix 的值是 t_ ,最后生成的文件就是 t_Gx655d 这样一个空的文件。

tmpfile() 在之前的文章中也讲解过,它是生成一个临时文件,一般会放在 /tmp 目录下(如果你没有修改 php.ini 文件中的相关设置的话)。这个函数创建文件后会返回一个句柄,一旦使用 fclose() 关闭了这个文件句柄,那么文件就马上会被删除掉。

按规则返回目录内容

foreach (glob("*.txt") as $filename) {
echo "$filename size: " . filesize($filename) , PHP_EOL;
}
// cp_test.txt size 8
// fpc_test.txt size 8
// ltest.txt size 8
// ltest2.txt size 8
// new_re_test.txt size 8
// test.txt size 8
// test3.txt size 0 foreach (glob("../../202009/*.md") as $filename) {
echo "$filename size: " . filesize($filename) , PHP_EOL;
}
// ./../202009/1.PHP中的PDO操作学习(三)预处理类及绑定数据.md size: 16881
// ../../202009/10.PHP中非常好玩的Calendar扩展学习.md size: 8784
// ../../202009/11.学习PHP中的国际化功能来查看货币及日期信息.md size: 5521
// ../../202009/12.PHP中的日期相关函数(一).md size: 14217
// ../../202009/13.PHP中的日期相关函数(二).md size: 9858
// ../../202009/2.PHP中的PDO操作学习(四)查询结构集.md size: 12825
// ../../202009/3.在PHP中使用SPL库中的对象方法进行XML与数组的转换.md size: 6068
// ../../202009/4.PHP中的MySQLi扩展学习(一)MySQLi介绍.md size: 6029
// ../../202009/5.PHP中的MySQLi扩展学习(二)mysqli类的一些少见的属性方法.md size: 9726
// ../../202009/6.PHP中的MySQLi扩展学习(三)mysqli的基本操作.md size: 9403
// ../../202009/7.PHP中的MySQLi扩展学习(四)mysqli的事务与预处理语句.md size: 3556
// ../../202009/8.PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作.md size: 7450
// ../../202009/9.PHP中的MySQLi扩展学习(六)MySQLI_result对象操作.md size: 10650

glob 函数也是之前有讲解过的一个函数,它会根据指定的规则返回目录中的所有文件或者目录信息。可以方便地用于目录地遍历操作。注意这里的规则参数不是完全的正则表达式,关于它具体支持的语法可以自行查阅相关的文档。

文件 umask 操作

$old = umask(0);
echo $old, PHP_EOL; // 18
$now = umask();
echo $now, PHP_EOL; // 0

umask() 函数就是操作当前执行进程的 umask 信息,和 Linux 中的 umask 命令一样,用于指定当前创建的目录文件的默认权限信息。在 PHP 中,umask() 将 PHP 的 umask 设定为 mask & 0777 ,并返回原来的 umask 。当 PHP 被作为服务器模块使用时,在每个请求结束后 umask 会被恢复。具体的 umask 知识大家可以参考 Linux 中的相关内容。

配置文件信息读取

最后这两个函数是用于读取 PHP 类型的配置文件信息的,什么叫 PHP 类型的配置文件信息?其实就是类似于 php.ini 文件那样的配置文件,key=value 这种形式的配置文件。就像 Laravel 的 .env 文件也是可以使用这两个函数进行读取的。

var_dump(parse_ini_file('/usr/local/etc/php/7.3/php.ini'));
// array(133) {
// ["#zend_extension"]=>
// string(9) "xdebug.so"
// ["extension"]=>
// string(6) "vld.so"
// ["engine"]=>
// ……
// …… var_dump(parse_ini_file('/usr/local/etc/php/7.3/php.ini', true));
// array(38) {
// ["#zend_extension"]=>
// string(9) "xdebug.so"
// ["extension"]=>
// string(6) "vld.so"
// ["PHP"]=>
// array(45) {
// ["engine"]=>
// string(1) "1"
// ["short_open_tag"]=>
// ……
// ……

parse_ini_file() 函数就是直接读取指定路径的配置文件内容,在这里我们直接测试的就是读取 php.ini 文件。它有一个可选参数,如果设置为 true 的话,返回的就是数组分类的结构化的内容。

$ini = file_get_contents('/usr/local/etc/php/7.3/php.ini');
var_dump(parse_ini_string($ini));
// array(133) {
// ["#zend_extension"]=>
// string(9) "xdebug.so"
// ["extension"]=>
// string(6) "vld.so"
// ["engine"]=>
// ……
// …… var_dump(parse_ini_string($ini, true));
// array(38) {
// ["#zend_extension"]=>
// string(9) "xdebug.so"
// ["extension"]=>
// string(6) "vld.so"
// ["PHP"]=>
// array(45) {
// ["engine"]=>
// string(1) "1"
// ["short_open_tag"]=>
// ……
// ……

parse_ini_string() 则是从给定的字符串中读取配置信息,同样也有一个格式化分组输出的参数可选。它和 parse_ini_file() 是完全相同的,唯一的区别就是一个是从文件路径读取,一个是从字符串读取。

总结

一口气介绍了这么多函数,大家是不是都用过呢?有人要说了,写这玩意干嘛,直接去看文档不就好了嘛?那可不一样哦,文档中很多函数的介绍就一句话,示例代码也都是使用英文注释的,咱这虽说也是一个搬运工,但咱不仅是简单地搬运了一下,还把例子重写了,另外还加上了一些应用场景的介绍哦!至于各位看官感觉好不好,那就仁者见仁,智者见智咯!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/7.PHP中的文件系统函数(二).php

参考文档:

https://www.php.net/manual/zh/ref.filesystem.php

===============

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP中的文件系统函数(二)的更多相关文章

  1. PHP中的文件系统函数(三)

    总算来到我们最关心的部分了,也就是 f 相关函数的操作.基本上大部分的文件操作都是以今天学习的这些内容为基础的,话不多说,我们就一个一个的来学习学习吧. 文件读取 文件的读取其实非常简单,fopen( ...

  2. PHP中的文件系统函数(一)

    从这篇文章开始,我们将学习一系列的 PHP 文件系统相关函数.其实这些函数中,有很多都是我们经常用到的,大家并不需要刻意地去记住它们,只要知道有这么个东西,在使用的时候记得来查文档就可以了. 文件路径 ...

  3. 在nodeJS中操作文件系统(二)

    在nodeJS中操作文件系统(二)   1. 移动文件或目录 在fs模块中,可以使用rename方法移动文件或目录,使用方法如下:     fs.rename(oldPath,newPath,call ...

  4. PYTHON练习题 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数。

    Python 练习 标签: Python Python练习题 Python知识点 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数,如果大于预设的 ...

  5. C#中的函数(二) 有参有返回值的函数

    接上一篇 C#中的函数(-) 无参无返回值的函数 http://www.cnblogs.com/fzxiaoyi/p/8502613.html 这次研究下C#中的函数(二) 有参有返回值的函数 依然写 ...

  6. Node.js之操作文件系统(二)

    Node.js之操作文件系统(二) 1.创建与读取目录 1.1 创建目录 在fs模块中,可以使用mkdir方法创建目录,该方法的使用方法如下: fs.mkdir(path,[mode],callbca ...

  7. 在Node.js中操作文件系统(一)

    在Node.js中操作文件系统 在Node.js中,使用fs模块来实现所有有关文件及目录的创建,写入及删除操作.在fs模块中,所有对文件及目录的操作都可以使用同步与异步这两种方法.比如在执行读文件操作 ...

  8. Spark Streaming中的操作函数讲解

    Spark Streaming中的操作函数讲解 根据根据Spark官方文档中的描述,在Spark Streaming应用中,一个DStream对象可以调用多种操作,主要分为以下几类 Transform ...

  9. 【转】嵌入式操作系统VxWorks中TFFS文件系统的构建

    时间:2005-02-20 来源:21IC中国电子网 作者:771所加固机工程部 蔡本华 高文炜 关键字:VxWorks   TFFS   嵌入式操作系统   文件系统       摘要:目前的嵌入式 ...

随机推荐

  1. linux虚拟机环境快速搭建redis5.x版本的主从集群总结

    文/朱季谦 我在阿里云服务器上曾参与过公司redis集群的搭建,但时间久了,都快忘记当时的搭建过程了,故而决定在虚拟机centOS 7的环境,自行搭建一套redis5.x版本的集群,该版本集群的搭建比 ...

  2. filter,interceptor,controllerAdvice,aspect,controller执行顺序

    1.filter,这是java的过滤器,和框架无关的,是所有过滤组件中最外层的,从粒度来说是最大的. 配置方式,有直接实现Filter+@component,@Bean+@configuration( ...

  3. 1065 A+B and C (64bit) (20分) 测试点3 别用cin

    cin的话,处理不了这么大的数?? 要拐回scanf("%lld"): 啊啦搜

  4. iOS开发之Lame编译

    前言 为了保证音频格式在多端通用,需要将音频转化为MP3格式,本文讲解了如何使用Shell脚本来编译lame库. 编译脚本 #!/bin/sh CONFIGURE_FLAGS="--disa ...

  5. unserialize反序列化 安鸾 Writeup

    关于php反序列化漏洞原理什么,可以看看前辈的文章: https://xz.aliyun.com/t/3674 https://chybeta.github.io/2017/06/17/浅谈php反序 ...

  6. 003 TCP/IP协议详解(一)

    TCP/IP TCP/IP 意味着 TCP 和 IP 在一起协同工作. TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信. IP 负责计算机之间的通信. TCP 负责将数据分割并装入 IP ...

  7. MySQL主从复制与Atlas读写分离

    配置主从复制 1. 增加主从配置 # 主库配置文件 server-id = 1 log-bin = /var/lib/mysql/mysql-bin expire_logs_days = 10 ski ...

  8. JSON.stringify()还可以这么用

    最近做项目的时候遇到一个对象深拷贝的问题,网上看了下发现最为简便的方法是JSON.stringify(),比如你要深拷贝一个对象,可以这么做: var test={ a:"hello&quo ...

  9. mybatis传入参数为0被误认为是空字符串的解决方法

    在mbatis中使用Xml配置sql语句时,出现了这样一个问题.当我传入的参数为0去做判断时,mybatis会把参数0当成是空字符串去判断而引起查询结果错误 所以在做项目时一定要注意,用到MyBati ...

  10. struts2思想学习(一)

    OOP 面向对象编程 AOP 面向切面编程 而在struts2 处处体现了面向切面编程的思想(动态代理最典型)! 拦截器其实也是面向切面编程!拦截器切断了所有请求到action的操作 并做了很多的前提 ...