前言遍历文件scandir给定目录非法使用dir函数递归法路径解析数据结构设计原理解析代码实现演示当前目录父级目录总结
这几天在看easyui,看到树形结构这个组件的时候突发奇想,能不能把站点以目录树的形式展示呢?
然后着手实现了一下,具体的来说是实现了对数据层的获取,还没有附加到tree组件上。下面就来谈谈我对这次文件信息抓取的体会吧。
在php中遍历文件有很多方式,但是适用的场景不尽相同。所以在合适的场合适用合适的方法显得至关重要,下面简要的了解一下。
如果说想找到一款类似于Python中使用os.walk
获取文件目录信息的优雅的方法,在PHP中就不是那么的方便了,唯一能称得上简单的就是scandir
函数,但是这个函数并不优雅,其作用就是扫描给定目录下的文件信息(如果包含子目录,那就只能显示到子目录的层级,再想查看子目录下的信息,那就不行了,否则会报错的)。
空口无凭,找个实例来看一下就一目了然了。
效果如下
所谓非法使用,就是指给出非目录文件时的场景,比如我们直接给个文件的路径,就是这样了。
<?php/** * Created by PhpStorm. * User: ${郭璞} * Date: 2017/2/3 * Time: 20:25 * Description: scandir函数测试 */$pathinfo = scandir('./scandir.php');var_dump($pathinfo);所以,使用scandir函数的时候务必明确这一点,传正确的参数!!!
既然使用scandir函数不行了,那咱们就换个思路呗。下面介绍一个比较常用的方法。
<?php/** * Created by PhpStorm. * User: ${郭璞} * Date: 2017/2/3 * Time: 20:25 * Description: scandir函数测试 */$path = ".";if(is_dir($path)) { $dirinfo = dir($path); while($file = $dirinfo->read()) { echo "<mark>".$file."</mark><br />"; } $dirinfo->close();}else if (is_file($path)) { echo "<font color='green'>".$path."</font>";}如果将$path='.'
换成$path='./scandir.php'
。将出现如下结果。
当然,这两个方法都没能实现我们想要的效果。不能突破子目录的情况,没办法遍历到最底层的文件信息。
既然如此,那就得另寻他法了。我个人觉得递归的方法不赖,应该可以灵活地处理这些问题,说做就做。
使用面向过程的PHP编码方法需要处理外部数组引用问题,显得代码不是很容易理解,所以我选择面向对象的方法,将外部数组封装到一个类中,专门用于处理这类问题。
<?php/** * Created by PhpStorm. * User: ${郭璞} * Date: 2017/2/3 * Time: 9:32 * Description: 读取给定目录及子目录下文件路径信息 */class FileWatcher{ public $fileinfo; /** * FileWatcher constructor. * @param $path 给定路径 */ function __construct(){ $this->fileinfo = array(); } /** * 去除路径设置信息,析构方法 */ function __destruct() { // TODO: Implement __destruct() method. $this->fileinfo = null; } public function scanDir($path) { if(is_dir($path)) { $tmpdir = dir($path); while($tmpfile = $tmpdir->read()) { if($tmpfile!='.' && $tmpfile!='..') $this->scanDir($path."/".$tmpfile); } $tmpdir->close(); } if(is_file($path)) { array_push($this->fileinfo, $path); } return $this->fileinfo; }}下面是测试时使用的代码。
$fileWatcher = new FileWatcher();$result = $fileWatcher->scanDir('.');var_dump($result);最终实现的效果为:
单单是这样,不是很好用。我就想着能不能实现类似于Python中os.walk
那样优雅的获取相关的信息呢?
使用过那个方法的应该都了解,获取到的元组信息非常的详细,包括路径啊,目录级啊什么的非常的详细。
但是我这边为了以后使用easyui的tree组件,可能需要处理一下目录深度的问题,所以我设计了下面的数据结构。比较简单,但是实用性感觉还是挺强的。
class FileInfo{ // 目录深度 public $level; // 文件经过的路径,以数组形势依次填充 public $pathstep; // 文件的完整路径 public $fullpath; public function __construct() { //pathstep 存储当前路径经过的文件夹信息 $this->pathstep = array(); } public function __destruct() { // TODO: Implement __destruct() method. $this->pathstep = null; $this->level = null; $this->fullpath = null; }}我个人认为原理还是比较简单的了,那就是以文件分隔符作为计算标准。当然了,需要处理一大堆的路径适配问题,尤其是./
和../
这样的相对路径。
处理完这些之后就轻松多了,使用explode
函数将字符串进行分割,装填到数组中即可。
下面演示一下实现的效果吧。
测试代码如下
//获取全部文件以及路径信息$fileWatcher = new FileWatcher();$result = $fileWatcher->scanDir('.');$pathParser = new PathParser($result);$resultSet = $pathParser->parse();echo json_encode($resultSet);结果图
对于父级目录信息获取,也是非常方便的。之前网上下载了easyui的压缩包,解压后扔到了apache服务器上,下面来看看对这个大文件信息集的获取情况吧。 测试代码把路径中的那个.
改成../easyui
即可。
结果还行吧。我看着挺详细的了。那么到这里就差不多实现预期的效果了。
回顾一下,今天主要是对于文件目录信息的遍历。
显示通过通用的scandir 函数和dir循环读取方式对目录进行了读取,但是效果不佳,于是转战递归实现。
为了达到一个更加优雅的信息获取效果,又设计了一个专门针对于文件的类,用于存储相关数据。
为了处理相对路径中本级目录和父级目录等特殊情况,又使用了substr和explode函数,最后封装成了一个通用的类,效果还不错。
缺点嘛,显而易见。代码的风格不是很好,命名什么的也是按照我自己的套路来的,不是很正规。
其他的貌似也没什么了,那就先这样好了。
新闻热点
疑难解答