php遍歷檔案的5種方式
在網上搜索了一下遍歷資料夾的函式,資料很多,但都不算特別的全。所以,今天粗略的總結一下,使用php 幾種常見的遍歷檔案的方式。
備註:大部分demo使用遞迴的方式進行條用
測試目錄如下圖:
一:使用scandir 函式
1.1 函式封裝
scandir : 是php 自帶函式,返回當前目錄下的所有檔案和資料夾。注意:會有 ‘.’ 和’..’,分別代編當前目錄和上層目錄。
/**
* 使用scandir 遍歷目錄
*
* @param $path
* @return array
*/
function getDir($path)
{
//判斷目錄是否為空
if(!file_exists($path)) {
return [];
}
$files = scandir($path);
$fileItem = [];
foreach($files as $v) {
$newPath = $path .DIRECTORY_SEPARATOR . $v;
if(is_dir($newPath) && $v != '.' && $v != '..') {
$fileItem = array_merge($fileItem , getDir($newPath));
}else if(is_file($newPath)){
$fileItem[] = $newPath;
}
}
return $fileItem;
}
1.2程式呼叫:
echo('遍歷目錄開始');
$path = realpath('./m1/');
var_dump(getDir($path));
echo('遍歷目錄結束');
1.3 顯示結果
/usr/local/opt/[email protected]/bin/php
遍歷目錄開始array(9) {
[0]=>
string(48) “/Users/niedewang/PhpstormProjects/test/m1/1.html”
[1]=>
string(48) “/Users/niedewang/PhpstormProjects/test/m1/2.html”
[2]=>
string(50) “/Users/niedewang/PhpstormProjects/test/m1/demo.txt”
[3]=>
string(54) “/Users/niedewang/PhpstormProjects/test/m1/m2/m2_1.html”
[4]=>
string(54) “/Users/niedewang/PhpstormProjects/test/m1/m2/m2_2.html”
[5]=>
string(54) “/Users/niedewang/PhpstormProjects/test/m1/m2/m2_3.html”
[6]=>
string(57) “/Users/niedewang/PhpstormProjects/test/m1/m2/m3/m3_1.html”
[7]=>
string(56) “/Users/niedewang/PhpstormProjects/test/m1/m2/m3/m3_2.php”
[8]=>
string(56) “/Users/niedewang/PhpstormProjects/test/m1/m2/m3/m3_3.txt”
}
遍歷目錄結束
Process finished with exit code 0
1.4 注意事項
- 難度係數:簡單
- 注意事項: 注意迴圈的時候,過濾 ‘.’ 和 ‘..’ ,否則可能會導致死迴圈
二:使用glob函式
2.1 函式封裝
glob:是php 子系統自帶函式,功能和scandir 類似,但比它更加強大靈活。
比如 :glob(‘*.txt’),將會列舉出目錄下的所有為站名為.txt 的檔案。
/**
* 使用glob 遍歷
* @param $path
*/
function getDir2($path)
{
//判斷目錄是否為空
if(!file_exists($path)) {
return [];
}
$fileItem = [];
//切換如當前目錄
chdir($path);
foreach(glob('*') as $v) {
$newPath = $path . DIRECTORY_SEPARATOR . $v;
if(is_dir($newPath)) {
$fileItem = array_merge($fileItem,getDir2($newPath));
}else if(is_file($newPath)) {
$fileItem[] = $newPath;
}
}
return $fileItem;
}
2.2 函式呼叫方式
echo('遍歷目錄開始');
$path = realpath('./m1/');
var_dump(getDir2($path));
echo('遍歷目錄結束');
2.3 :顯示結果,同1.3 一致,不再展示
2.4 注意事項
- 難易程度:非常容易,不需要過濾 . 和 ..
- 靈活程度:非常靈活
三:使用opendir 函式
3.1 函式封裝
opendir : 返回一個目錄控制代碼,可以使用readdir 讀取這個目錄,也可以通過closedir 關閉這個目錄
/**
* 使用opendir 函式遞迴
*/
function getDir3($path)
{
if(!file_exists($path)) {
return [];
}
$handle = opendir($path);
$fileItem = [];
if($handle) {
while(($file = readdir($handle)) !== false) {
$newPath = $path . DIRECTORY_SEPARATOR . $file;
if(is_dir($newPath) && $file != '.' && $file != '..') {
$fileItem = array_merge($fileItem,getDir3($newPath));
}else if(is_file($newPath)) {
$fileItem[] = $newPath;
}
}
}
@closedir($handle);
return$fileItem;
}
3.2 呼叫方式
echo('遍歷目錄開始');
$path = realpath('./m1/');
var_dump(getDir5($path));
echo('遍歷目錄結束');
3.3 注意事項
需要過濾 ‘.’ 和 ”
四:使用dir 函式
4.1 和opendir 函式非常類似,它更加的面向物件。
/**
* dir 函式的方式,物件
*
* @param $path
* @return array
*/
function getDir4($path) {
if(!file_exists($path)) {
return [];
}
$handel = dir($path);
$fileItem = [];
if($handel) {
while(($file = $handel->read()) !== false) {
$newPath = $path . DIRECTORY_SEPARATOR . $file;
if(is_dir($newPath) && $file != '.' && $file != '..') {
$fileItem = array_merge($fileItem,getDir4($newPath));
}else if(is_file($newPath)) {
$fileItem[] = $newPath;
}
}
}
$handel->close();
return $fileItem;
}
4.4 注意事項
需要過濾 ‘.’ 和 ”
五:使用spl 庫
使用spl 庫中的物件,好處是不需要進行迭代,書寫起來非常容易
/**
* 使用 spl 庫
*
* @param $path
*/
function getDir5($path)
{
$dir = new RecursiveDirectoryIterator($path);
$fileItem = [];
foreach(new RecursiveIteratorIterator($dir) as $k=>$v) {
$fileName = $v->getBaseName();
if($fileName != '.' && $fileName != '..') {
$fileItem[] = $k;
}
}
return $fileItem;
}
5.2 呼叫方式:
echo('遍歷目錄開始');
$path = realpath('./m1/');
var_dump(getDir4($path));
echo('遍歷目錄結束');
5.3 注意事項:
難以程度:容易。
- 類名有點長,但非常容易使用,畢竟不需要自己寫迭代函數了。
- 不需要處理 . 和 .. 兩個特殊目錄
六:總結
- 如果目錄數量不是很多,建議使用 scandir 方式,應為函式名容易記憶。
- 如果要求靈活性,比如只顯示某一型別的檔案等,使用glob 方式,
本身就有類似搜尋的功能。 - 如果目錄下檔案較多,建議使用opendir 和dir 的方式。
- 因為scandir 和glob都是返回滿足條件的所有檔案,如果有幾十萬這樣,返回素組非常龐大。
opendir迴圈可控性要強一些,比如可以返回前100個檔案等。這個還需要論證 - 如果希望程式碼簡介,使用spl 庫的方式。程式碼量少