前言遍歷文件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函數,最后封裝成了一個通用的類,效果還不錯。
缺點嘛,顯而易見。代碼的風格不是很好,命名什么的也是按照我自己的套路來的,不是很正規。
其他的貌似也沒什么了,那就先這樣好了。
新聞熱點
疑難解答