对于 SPL 来说,除了咱们之前学习到的各种 数据结构 以及 迭代器 之外,还有一类十分好用的性能就是对于文件的操作。明天咱们就来学习这方面的内容,同时,这也是 SPL 系列文章中最初要学习的内容。
文件操作
对于 PHP 的文件操作来说,在默认状况下咱们都是应用面向过程的那些函数来进行操作,比方 fopen()、fwrite()、fread()、fgets() 这些。而 SPL 中提供的则是以面向对象的形式来进行这些文件相干的操作。
文件信息类
首先咱们要学习的是 SplFileInfo 这个类。
$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_AoLQg
- PHP 中的文件系统函数(二):https://mp.weixin.qq.com/s/8THIW4du-Y5HMefRNIV2RA
- PHP 中的文件系统函数(三):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