本文探讨 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中文网其他相关文章!