本文探討 PHP 應用開發中常見的任務:列出文件和目錄。我們將介紹幾種基本和高級的解決方案,並分析其優缺點。首先,我們將介紹三種使用基本 PHP 函數的方法,然後逐步過渡到利用 SPL 迭代器的更強大的方法。為方便討論,我們假設目錄結構如下:
<code>---manager | ---user | ---document.txt | ---data.dat | ---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt</code>
glob()
、opendir()
、readdir()
、closedir()
和 scandir()
。這些函數的靈活性各不相同,有些需要後期過濾。 FilesystemIterator
、RecursiveDirectoryIterator
和 GlobIterator
。這些迭代器可以擴展以更好地滿足特定需求。 glob()
函數是一種單行解決方案,允許過濾,但缺乏靈活性。相反,opendir()
、readdir()
和 closedir()
提供更大的靈活性,但需要更冗長的代碼和後期過濾。 scandir()
函數也需要後期過濾,但不需要管理文件句柄。對於面向對象的方法,應使用 SPL 庫。 GlobIterator
允許預過濾,而其他迭代器可以使用 RegexIterator
實現相同的功能。 第一組方法演示了 glob()
函數的使用,opendir()
、readdir()
和 closedir()
函數的組合,以及 scandir()
函數的使用。
glob()
第一個要討論的函數是 glob()
,它允許我們使用與最著名的 shell 類似的通配符來搜索路徑名。該函數有兩個參數:
$pattern
(必填):搜索模式$flags
(可選):官方文檔中列出的一個或多個標誌讓我們看一些例子!要在目錄中搜索所有以 *.txt
結尾的文件和目錄,您可以編寫:
<?php $filelist = glob("*.txt");
如果您顯示 $filelist
,輸出將是:
<code>array ( 0 => 'article.txt', 1 => 'text.txt' )</code>
如果您想要以“te”開頭的文件和目錄列表,則要編寫的代碼是:
<?php $filelist = glob("te*");
輸出是:
<code>array ( 0 => 'test.dat', 1 => 'text.txt' )</code>
要僅獲取包含“ma”的目錄列表,代碼如下:
<?php $filelist = glob("*ma*", GLOB_ONLYDIR);
在這個最後一個例子中,輸出是:
<code>---manager | ---user | ---document.txt | ---data.dat | ---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt</code>
請注意,最後一個示例使用 GLOB_ONLYDIR
常量作為可選的第二個參數。如您所見,名為 master.dat
的文件被排除在外。儘管 glob()
函數易於使用,但在某些情況下它並不靈活。例如,它沒有標誌來僅檢索與給定模式匹配的文件(而不是目錄)。
opendir()
和 readdir()
我想討論的第二種讀取文件和目錄的方法涉及 opendir()
、readdir()
和 closedir()
函數。 opendir()
打開目錄並返回連接句柄。檢索到句柄後,您可以使用 readdir()
。每次調用此函數時,它都會在打開的目錄中給出下一個文件或目錄的名稱。檢索到所有名稱後,該函數返回 false
。要關閉句柄,您可以使用 closedir()
。與 glob()
不同,這種方法稍微複雜一些,因為您沒有參數來幫助您過濾返回的文件和目錄。您必須自己執行後期過濾才能獲得所需內容。為了與 glob()
函數並行,以下示例檢索所有以“te”開頭的文件和目錄的列表:
<?php $filelist = glob("*.txt");
輸出與之前的示例相同。但是,如果您執行上面的代碼並在運行時輸出 $entry
的值,您會發現它有時包含一些奇怪的條目:“.”和“..” 。這些是您在文件系統每個目錄中都會找到的兩個虛擬目錄。它們分別代表當前目錄和父目錄(上一級文件夾)。第二個示例顯示如何僅檢索給定路徑中包含的文件。
<code>array ( 0 => 'article.txt', 1 => 'text.txt' )</code>
正如您可能猜到的那樣,使用上面的代碼會產生以下輸出:
<?php $filelist = glob("te*");
scandir()
最後,我想介紹 scandir()
函數。它只有一個必填參數:要讀取的路徑。返回值是路徑中包含的文件和目錄的數組。與最後一個解決方案一樣,要檢索文件和目錄的子集,您必須自己進行後期過濾。另一方面,正如您從下面的代碼中看到的,此解決方案更簡潔,不需要管理文件句柄。此示例顯示如何檢索以字符串“te”開頭的文件和目錄:
<code>---manager | ---user | ---document.txt | ---data.dat | ---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt</code>
現在讓我們談談一些 SPL 迭代器。但在深入討論它們的使用之前,讓我介紹它們和 SPL 庫。 SPL 提供一系列面向對象的數據結構、迭代器、文件處理程序和其他功能的類。優點之一是迭代器是類,因此您可以擴展它們以更好地滿足您的需求。另一個優點是它們具有非常有用的原生方法,可以幫助您完成許多可能面臨的常見任務,並且您只需在一個地方就能找到它們。例如,在readdir()
中使用FilesystemIterator
,兩者都將在循環中使用,但使用readdir()
時,您的條目只是一個字符串,使用FilesystemIterator
時,您擁有一個可以為您提供有關該文件或目錄的大量信息的物件(大小、所有者、權限等)。當然,PHP 可以使用 filesize()
和 fileowner()
等函數為您提供相同的信息,但 PHP5 已將其方法轉向 OOP。因此,總而言之,我的建議是在此處遵循該語言的新最佳實踐。如果您需要有關 SPL 迭代器的更多一般信息,請查看使用 SPL 迭代器。如引言中所述,我將展示 FilesystemIterator
、RecursiveDirectoryIterator
和 GlobIterator
的使用。第一個繼承自 DirectoryIterator
,而其他繼承自 FilesystemIterator
。它們都具有相同的構造函數,該構造函數只有兩個參數:
$path
(必填):要迭代的文件系統項目的路徑$flags
(可選):官方文檔中列出的一個或多個標誌這些迭代器的實際區別在於它們導航給定路徑的方法。
FilesystemIterator
使用 FilesystemIterator
非常簡單。為了展示它的實際應用,我將展示兩個示例。在第一個示例中,我將搜索所有以字符串“te”開頭的文件和目錄,而第二個示例將使用另一個迭代器RegexIterator
來搜索所有以“t.dat”或“t. php”結尾的文件和目錄。 RegexIterator
用於基於正則表達式過濾另一個迭代器。
<?php $filelist = glob("*.txt");
使用上面的代碼,結果與之前的示例相同。使用 RegexIterator
的第二個示例是:
<code>array ( 0 => 'article.txt', 1 => 'text.txt' )</code>
在這種情況下,輸出是:
<code>---manager | ---user | ---document.txt | ---data.dat | ---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt</code>
RecursiveDirectoryIterator
RecursiveDirectoryIterator
提供了一個接口,用於遞歸迭代文件系統目錄。由於其目標,它有一些有用的方法,例如 getChildren()
和 hasChildren()
,它們分別返回當前條目的迭代器(如果它是目錄)以及當前條目是否為目錄。為了展示 RecursiveDirectoryIterator
和 getChildren()
的實際應用,我將重寫最後一個示例以獲得相同的結果。
<?php $filelist = glob("*.txt");
GlobIterator
GlobIterator
以類似於 glob()
函數的方式迭代文件系統。因此,第一個參數可以包含通配符。下面的代碼顯示了使用 GlobIterator
的常用示例。
<code>array ( 0 => 'article.txt', 1 => 'text.txt' )</code>
在本文中,我說明了實現相同目標的不同方法:如何在給定路徑中檢索和過濾文件和目錄。以下是一些需要記住的關鍵點:
glob()
函數是一種單行解決方案,允許過濾,但它不是很靈活。 opendir()
、readdir()
和 closedir()
的解決方案有點冗長,需要後期過濾,但更靈活。 scandir()
函數也需要後期過濾,但不需要管理句柄。 GlobIterator
能夠進行預過濾,但其他迭代器可以使用 RegexIterator
以舒適的方式實現相同的功能。 您是否知道實現此目標的其他方法?如果是,並且您想與我們分享,請繼續。知識共享始終受到歡迎。 圖片來自 Fotolia
可以使用 sort()
函數在 PHP 中對文件和目錄進行排序。在使用 scandir()
函數檢索文件和目錄後,您可以應用 sort()
函數以升序排列它們。如果您想以降序排列它們,可以使用 rsort()
函數。請記住將文件和目錄數組作為參數傳遞給這些函數。
要排除某些文件或目錄,您可以將 in_array()
函數與 scandir()
函數結合使用。 in_array()
函數檢查某個值是否存在於數組中。您可以創建一個要排除的文件或目錄數組,然後使用 in_array()
函數檢查文件或目錄是否存在於該數組中。如果存在,您可以跳過它。
要僅列出目錄而不是文件,您可以使用 is_dir()
函數。此函數檢查某個路徑是否為目錄。您可以將其與 scandir()
函數結合使用,以檢查 scandir()
返回的數組中的每個項目是否為目錄。如果是,您可以將其包含在您的列表中。
要遞歸列出文件和目錄,您可以創建一個遞歸函數,該函數使用 scandir()
函數獲取文件和目錄,然後為它找到的每個目錄調用自身。這將允許它遍歷整個目錄樹。
要獲取每個文件的大小,您可以使用 filesize()
函數。此函數以字節為單位返回文件的大小。您可以將其與 scandir()
函數結合使用,以便在列出文件時獲取每個文件的大小。
要獲取每個文件的最後修改日期,您可以使用 filemtime()
函數。此函數以 Unix 時間戳的形式返回文件的最後修改時間。您可以將其與 scandir()
函數結合使用,以便在列出文件時獲取每個文件的最後修改日期。
要按擴展名過濾文件,您可以使用 pathinfo()
函數。此函數返回有關文件路徑的信息,包括擴展名。您可以將其與 scandir()
函數結合使用,以便在列出文件時按擴展名過濾文件。
要列出遠程目錄中的文件和目錄,您可以使用 ftp_nlist()
函數。此函數返回 FTP 服務器上指定目錄中文件和目錄的列表。在使用 ftp_nlist()
之前,您需要使用 ftp_connect()
和 ftp_login()
函數建立 FTP 連接。
要處理列出文件和目錄時的錯誤,您可以使用 error_reporting()
和 set_error_handler()
函數。這些函數允許您設置錯誤報告級別並定義一個自定義錯誤處理程序函數,該函數將在發生錯誤時被調用。
要列出 ZIP 存檔中的文件和目錄,您可以使用 ZipArchive
類。此類提供用於處理 ZIP 存檔的方法,包括 getFromName()
方法,該方法允許您檢索存檔中文件的內容。
以上是PHP主|列出PHP的文件和目錄的詳細內容。更多資訊請關注PHP中文網其他相關文章!