$file = new SplFileInfo('./6.PHP的SPL扩展库(四)函数.php');
实例化它的时候,就须要通报一个文件路径参数。比如这里我们就直接打开上一篇文章的测试代码。然后,我们的 $file 变量就会得到一个 SplFileInfo 工具,在这个工具中,有许多和文件函数类似的方法可以供我们利用。
var_dump($file->getBasename());// string(39) "6.PHP的SPL扩展库(四)函数.php"var_dump($file->getPathname());// string(41) "./6.PHP的SPL扩展库(四)函数.php"var_dump($file->getFilename());// string(39) "6.PHP的SPL扩展库(四)函数.php"var_dump($file->getRealPath());// string(102) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/2021/01/source/6.PHP的SPL扩展库(四)函数.php"var_dump($file->getPathInfo());// object(SplFileInfo)#2 (2) {// ["pathName":"SplFileInfo":private]=>// string(1) "."// ["fileName":"SplFileInfo":private]=>// string(1) "."// }var_dump($file->getFileInfo());// object(SplFileInfo)#2 (2) {// ["pathName":"SplFileInfo":private]=>// string(41) "./6.PHP的SPL扩展库(四)函数.php"// ["fileName":"SplFileInfo":private]=>// string(39) "6.PHP的SPL扩展库(四)函数.php"// }
我们可以通过上面的这些测试代码来得到文件干系的一些路径信息。是不是和普通的那些文件操作函数非常类似,或者说是完备一样的命名和利用办法。
var_dump($file->getExtension());// string(3) "php"var_dump($file->getType());// string(4) "file"var_dump($file->getCTime());// int(1611017967)var_dump($file->getOwner());// int(501)var_dump($file->getGroup());// int(20)var_dump($file->getSize());// int(3543)
当然,文件的这些属性信息也都是可以正常获取到的,比如文件的 扩展名、类型、各种文件干系的韶光、拥有者、属组、大小 之类的信息。

var_dump($file->isReadable());// bool(true)var_dump($file->isWritable());// bool(true)var_dump($file->isDir());// bool(false)var_dump($file->isFile());// bool(true)var_dump($file->isLink());// bool(false)
当然,判断文件是否可写、可读,是否是目录或文件或连接的方法都有。总体来说,普通的文件操作函数所拥有的功能这边都是存在的,在这里我们也只是列出了一部分,更多的方法大家可以在官方文件中查阅。
文件操作类上面的 SplFileInfo 中,我们彷佛没有对文件进行读写操作之类的功能,只能看到文件的一些属性信息。别急,对付文件的其它操作,我们利用其余一个类 SplFileObject 。它是继续自 SplFileInfo 的,并且其余又多实现了两个迭代器的接口。关于这两个多实现的接口的功能我们在后面会讲到。而相对付 SplFileInfo 来说,它扩展了文件的一些读写方法,能够让我们方便地进行文件的各种读写操作。
$txt1 = new SplFileObject('7.1.txt', 'a+');$txt1->fwrite(date('Y-m-d H:i:s' . PHP_EOL));// 71.txt// 2021-01-20 09:03:15// ……// ……
在实例化的时候,我们就可以通过 SplFileObject 的第二个参数来指定文件打开的形式,这个参数和 fopen() 函数中的干系参数的浸染是一样的。这里我们利用的是 a+ ,也便是追加读写的能力。由于我们要不断地测试,以是利用的便是这样的一个读写属性。在实例化之后,我们利用工具的 fwrite() 方法就可以正常的向文件中进行写入了。
$txt1->seek(0);var_dump($txt1->fread($txt1->getSize()));// string(80) "2021-01-20 09:03:15// "
对付读取来说,我们要先将文件工具内部的句柄指针指回开头处。这里利用的 seek() 方法是不是很眼熟。没错,它的涌现正是 SplFileObject 实现了 Seekable 接口的最好证明。接着,我们利用 fread() 就可以读取文件中的全部内容了。
当然,像是在普通的文件函数中最经典的 eof + fgets 这种遍历办法在 SplFileObject 中也是支持的,同样,它也支持 fgetc 、fgetss 这些方法。
$txt1->seek(0);while(!$txt1->eof()){ var_dump($txt1->fgets());}// string(20) "2021-01-20 09:03:15// "// string(20) "2021-01-20 09:03:16// "// ……// ……
前面说过,SplFileObject 是继续了一些迭代器接口的,也便是说,我们可以直接遍历这个工具来得到文件里面的内容。
foreach($txt1 as $t){ var_dump($t);}// string(20) "2021-01-20 09:03:15// "// string(20) "2021-01-20 09:03:16// "// ……// ……
是不是很神奇?这确实是 SplFileObject 中非常神奇的一个地方。通过这种办法我们直接就可以通过 foreach() 来实现对文件内容的遍历,而且可以看出,这种遍历形式也是按行来进行遍历的,完备可以替代上面的 eof+fgets 的办法。
关于普通的面向过程的文件操作函数的学习我们在之前的文章中已经学习过了,当中大部分的函数在 SplFileInfo 和 SplFileObject 中都可以找到对应的实现,这里就不进行更多的演示了。如果对文件操作干系函数还有什么疑问的同学,可以移步之前的文章再温习一下:
PHP中的文件系统函数(一):https://mp.weixin.qq.com/s/T7771zfScS1clCIg_AoLQgPHP中的文件系统函数(二):https://mp.weixin.qq.com/s/8THIW4du-Y5HMefRNIV2RAPHP中的文件系统函数(三):https://mp.weixin.qq.com/s/DU8ImuVYCmN2a83JAMU5CQ临时文件类关于文件干系操作我们末了再学习一个对付临时文件的操作。还记得之前我们学习过的 《在PHP中操作临时文件》https://mp.weixin.qq.com/s/bktuy1XSQ0TLOyGtMWe42g 吧,同样地,在 SPL 库中也有对应的操作临时文件的类。
$tmp = new SplTempFileObject(0);$tmp->fwrite("tmp:" . date('Y-m-d H:i:s'));$tmp->rewind();foreach ($tmp as $line) { var_dump($line);}// string(23) "tmp:2021-01-20 09:14:34"sleep(10);// vim /tmp/phpRhgsVZ// tmp:2021-01-20 09:14:34
怎么样,是不是也和 tmpfile() 一样通过在 /tmp 目录来保存临时文件,并且在程序运行结束后直接删除了文件。不过这里须要把稳的是,我们的 SplTempFileObject 类在实例化的时候通报了一个 0 作为参数,表示的是不该用内存作为临时文件目录,而是真实地存放在临时文件目录中。如果这个参数不填或者是填大于 0 的数字,则表示是将这个临时文件存放在内存中,而大于 0 的数字则表示所利用的内存大小,不填的话默认值是 2MB 。
目录遍历迭代器目录迭代器便是我们在之前讲迭代器中没有讲到的部分,也是我们说过要放在文件目录干系的文章中再讲到的内容。实在这方面的内容我们在之前也学习过,《PHP获取目录中的全部内容RecursiveDirectoryIterator》https://mp.weixin.qq.com/s/W8jE-AXZI18AhSMAPQlGYA 中利用的这个 RecursiveDirectoryIterator 便是 SPL 中的 递归目录迭代器 。本日,我们再学习一个比较大略的,也是这个 RecursiveDirectoryIterator 迭代器的上级迭代器,便是普通的目录迭代器的利用。
foreach (new DirectoryIterator('./') as $fileInfo) { if($fileInfo->isDot()) continue; if($fileInfo->isDir()){ echo "dir: " . $fileInfo->getFilename() , PHP_EOL; }else{ echo "file: " . $fileInfo->getFilename() , PHP_EOL; }}// file: 2.学习理解PHP中的SeasLog日志扩展.php// dir: autoloadA// file: 7.1.txt// file: 6.PHP的SPL扩展库(四)函数.php// file: 1.PHP中的一些杂项函数学习.php// file: browscap.ini// file: 7.PHP的SPL扩展库(四)文件及设计模式.php// file: 3.PHP的SPL扩展库(一)数据构造.php// file: 4.PHP的SPL扩展库(二)工具数组与数组迭代器.php// file: 1.txt// dir: autoloadB// file: 5.PHP的SPL扩展库(三)迭代器.php
同样非常大略的代码,这里就不多阐明了。而它和带 递归 功能的迭代器干系的差异和其它的迭代器都一样,也是在之前的文章都讲解过的,这里就不多赘述了。
设计模式末了,我们再来复习一下 设计模式 。设计模式系列文章是较早之前写过的一系列文章了。当时就在两篇文章中讲到过 SPL 中为我们准备好并且已经实现了的一些设计模式。
迭代器迭代器相信已经不用多说了,前面的文章 《PHP的SPL扩展库(三)迭代器》https://mp.weixin.qq.com/s/KevUTCbfmEPLuu5TvD0SSw 中已经详细解释了 SPL 中各种迭代器的实现。而对付迭代器这种设计模式,也可以参考我们之前的文章 《PHP设计模式之迭代器模式》https://mp.weixin.qq.com/s/uycac0OXYYjAG1BlzTUjsw 进行深入的学习理解。其余,Iterator 这个类不是 SPL 扩展中的哦!
SPL 库中只是有几种不同的详细迭代器实现而已。
除了迭代器,另一个便是不雅观察者模式,SPL 库中直接为我们准备好了 SplObserver 和 SplSubject 这两个类来专门用于实现不雅观察者模式。详细的实当代码和这个设计模式的讲解我们也在之前的设计模式系列文章中有过详细的解释,大家可以再过去好好学习下 《PHP设计模式之不雅观察者模式》https://mp.weixin.qq.com/s/SlSToMIGNBtU06BWNCwWvg 。
总结从这篇文章中可以看出一个问题,那便是 SPL 扩展库现在已经非常常用了,要不这里也不会有这么多之前文章的链接。相信大家也会在将来的业务开拓中更多地利用 SPL 中操作文件的类来进行文件操作,这也是一种趋势,毕竟面向工具的方法才是更主流的方法。好了,又是一个大扩展的完结,SPL 库作为一个已经默认集成到官方的扩展,确实是值得我们花更多的韶光来学习节制的,学习好这个扩展一定不会让你失落望!
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/01/source/7.PHP的SPL扩展库(五)文件及设计模式.php
参考文档:
https://www.php.net/manual/zh/book.spl.php