Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Einführung in das PHP-Dateisystem

Detaillierte Einführung in das PHP-Dateisystem

不言
不言Original
2018-07-20 09:51:131958Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Einführung in das PHP-Dateisystem. Freunde in Not können darauf zurückgreifen.

Heute beginnen wir eine neue Erkundungsreise, bei der wir tief in das PHP-Dateisystem eintauchen und systematisch die grundlegende Verwendung des PHP-Dateisystems erlernen und beherrschen.

Ich glaube, dass sich jeder im täglichen Forschungs- und Entwicklungsprozess zwangsläufig mit verschiedenen Dokumenten auseinandersetzen muss. Öffnen Sie beispielsweise die Datei .env und lesen Sie die Konfigurationsinformationen daraus, schreiben Sie die Fehlerinformationen im Projekt in die Protokolldatei oder rufen Sie die Erstellungszeit des Images ab usw. Beim Umgang mit diesen Funktionen müssen wir alle die PHP-Dateisystemschnittstelle verwenden.

Das Folgende ist eine Übersicht über die in diesem Artikel behandelten Themen:

  • 1. Was ist ein Dateisystem?

  • 2. Detailliertes PHP-Dateisystem

  • Drei objektorientierte Verzeichnisdurchquerung

  • Vier PHP-Dateisystem-Mindmap

Dieser Artikel ist länger und dauert etwa 20 Minuten, seien Sie also auf den Kampf vorbereitet!

1 Was ist ein Dateisystem?

Bevor wir beginnen, müssen wir zunächst den Problembereich, den wir untersuchen, klären und verstehen, was ein Dateisystem ist und was wir untersuchen.

In einem Computer wird das Dateisystem (Dateisystem oder Dateisystem) verwendet, um zu verwalten, wie Daten gespeichert und abgerufen werden. - Wikipedia

Um es einfach auszudrücken: So sollten wir unsere Verzeichnisse (Ordner) und Dateien verwalten. Normalerweise speichern wir Dateien mit ähnlichen Attributen für die spätere Suche im selben Verzeichnis. Dieser allgemeine Vorgang umfasst Verzeichnisse und Dateien.

Für Softwareentwickler besteht ein sehr typisches Nutzungsszenario darin, die Dateien von Controllern, Ansichten, Modellen und anderen Modulen in verschiedenen Verzeichnisstrukturen zu speichern, wenn sie MVC-Projekte entwickeln.

In jedem Fall unterteilen wir Dateien und Verzeichnisse nach unterschiedlichen Merkmalen, um das Problem der Dateispeicherung und -suche zu lösen.

Nachdem wir diese Erkenntnisse gewonnen haben, sollten wir natürlich über den Untersuchungsgegenstand des PHP-Dateisystems (oder Dateisystems) nachdenken, das wir gerade untersuchen. Eine einfache Zusammenfassung lautet:

  1. Verzeichnis (Ordner)

  2. Datei

Mit anderen Worten, die Verarbeitung der PHP-Dateisystemfunktionen, die wir in diesem Artikel erklären, dreht sich im Grunde rund um Verzeichnisse und Dateien.

2 Ausführliches PHP-Dateisystem

Mehr als 80 verfügbare Dateisystemfunktionen sind in das PHP-Dateisystem integriert. Aufgrund der Vielzahl leistungsstarker Funktionen kann dieser Artikel natürlich nicht alle Systemfunktionen einzeln erklären. Erstens ist die Zeit zu knapp; zweitens haben wir nicht so viel Energie, um sie alle in kurzer Zeit zu meistern.

Trotzdem müssen Sie sich nicht entmutigen lassen. Dieser Artikel wird nur begrenzte Zeit und Energie aufwenden, um die folgenden allgemeinen Themen der Dateiverarbeitung zu studieren:

  • Dateiverarbeitung So erhalten Sie Metadaten

  • So erhalten Sie den MIME-Typ einer Datei

  • Operationsverarbeitung von Dateien und Verzeichnissen

  • Berechtigungsverwaltung von Dateien und Verzeichnissen

Außerdem stellt uns die PHP-Standardfunktionsbibliothek nicht nur prozessorientierte Dateisystemverarbeitungsfunktionen zur Verfügung. Gleichzeitig kapselt es auch die objektorientierte Schnittstelle und die Iteratorschnittstelle für allgemeine Verzeichnis- und Dateioperationen, die jeder nutzen kann:

  • SplFileInfo

  • finfo

  • DirectoryIterator

  • RecursiveDirectoryIterator

2.1 Dateisystem-Metadaten

2.1.1 Was sind Metadaten?

Metadaten: Für den Laien sind es „Daten von Daten“. Nehmen Sie als Beispiel eine PHP-Datei. Ihre Metadaten können Erstellungszeit, Dateiname, Dateigröße oder Dateiberechtigungen usw. sein. Diese Art von Daten, die die grundlegenden Eigenschaften der Datei angeben können, sind „Metadaten“.

2.1.2 Häufig verwendete Metadatenerfassung

In diesem Abschnitt lernen wir einige Dateimetadatenfunktionen kennen, die häufig zum Abrufen benötigt werden, darunter:

  1. Letzte Änderungszeit der Datei abrufen

  2. Letzte Zugriffszeit der Datei abrufen

  3. Pfadinformationen der Datei abrufen

  4. Absoluten Pfad der Datei abrufen

  5. Dateityp abrufen

  6. Dateigröße abrufen

  7. Dateiberechtigungen abrufen

  8. Benutzer und Benutzergruppe abrufen, zu denen die Datei gehört

Ohne Nochmals, Ärmel hochkrempeln und loslegen!


  1. Erhalten Sie die letzte Änderungszeit der Datei

Um den letzten geänderten Zeitstempel einer Datei zu erhalten, können wir die Funktion filemtime($filename) oder die Methode SplFileInfo::getMTime() verwenden.

Beachten Sie, dass die SplFileInfo-Klasse bei der Instanziierung den Dateipfad $filename als Parameter erhält. Wenn es später keine spezielle Erklärung gibt, haben wir standardmäßig bereits die SplFileInfo-Instanz erhalten, bevor wir getMTime() und andere ausführen können ähnliche Verarbeitung.
// 文件路径请求改成你自己的文件路径
$filename = "f://filesystem/test.txt";

// 面向过程: 获取文件时间
$modifyTimestamp = filemtime($filename);

// 面向对象
$file = new SplFileInfo($filename);
$modifyTimestamp = $file->getMTime();
  • 2 Holen Sie sich die letzte Zugriffszeit der Datei

可以使用函数 fileatile($filename) 或 SplFileInfo::getATime() 方法,来获取文件的最后被访问时间戳。

// 文件路径请求改成你自己的文件路径
$filename = "f://filesystem/test.txt";

// 面向过程: 获取文件时间
$accessTimestamp = fileatime($filename);

// 面向对象
$file = new SplFileInfo($filename);
$accessTimestamp = $file->getATime();

除了 filemtilefileatime 之外,还有 filectime 来获取文件的 inode 修改时间(可认为是创建时间)。

有关时间的函数常用的就这些,为了方便记住,我们来看看它们是如何命名的:

  • 2.1 面向过程 file 前缀,面向对象 get 前缀

  • 2.2 a: access(访问);m:modify(修改);c:create(创建)

  • 2.3 time 后缀

  • 2.4 fileatime,SplFileInfo::getATime;filemtime,SplFileInfo::getMTime;filectime,SplFileInfo::getCTime。

是不是很简单呢!

注意,使用 filectime 时,对于 Windows 系统会获取创建时间,但对于类 Unix 系统是修改时间,因为在类 Unix 系统中多数文件系统并没有创建时间的概念。具体说明可以看 PHP: how can I get file creation date?。
  • 3 获取文件的路径信息

除了时间这些元数据,另一个经常遇到的情况是获取文件的路径信息,包括:

  • 3.1 目录信息

获取目录信息我们可以使用 pathinfo($filename, PATHINFO_DIRNAME)](http://php.net/manual/zh/function.pathinfo.php)**、**[dirname($filename)SplFileInfo::getPath()

比如下面给出的文件:

$filename = 'F:\Program Files\SSH Communications Security\SSH Secure Shell\Output.txt';

将会获取到 F:\Program Files\SSH Communications Security\SSH Secure Shell 这部分目录信息。

  • 3.2 文件名信息

这里我们所有的文件名指的是不带扩展名后缀的文件名称,比如需要获取 your_path/filename.txt 中的 filename 部分。

需要取得文件名信息,我们可以使用 pathinfo($filename, PATHINFO_FILENAME)](http://php.net/manual/zh/function.pathinfo.php)**、**[basename($filename, $suffix)](http://php.net/manual/zh/function.basename.php)** 和 **[SplFileInfo::getBasename($suffix) 获取。

这里给出的 $suffix** 指不获取 **$suffix 扩展名部分(比如不获取 $suffix = '.txt')。

请看下面的示例:

$filename = 'F:\Program Files\SSH Communications Security\SSH Secure Shell\Output.txt';

将会获取到 Output 这部分文件名信息。

  • 3.3 扩展名信息

扩展名我们可以使用 pathinfo($filename, PATHINFO_EXTENSION)SplFileInfo::getExtension() 方法拿到。

基于前面的了解,我们可以获取到 txt 这部分扩展信息,这里不再赘述。

  • 3.4 basename(文件名 + 扩展名)信息

basename 指的是 文件名 + 扩展名 内容信息,可以使用 pathinfo($filename, PATHINFO_BASENAME)](http://php.net/manual/zh/function.pathinfo.php)**、 **[basename($filename)SplFileInfo::getBasename()SplFileInfo::getFilename() 方法拿到。

虽然这里我们列出了很多的函数,但是基本上还是比较容易理解的,需要注意的是:

  • pathinfo 可以获取所有文件相关的路径信息,如果指定第二个参数选项将仅获取该部分的信息

  • 文件名和 basename 不是特别容易理解,你可以使用完全相同的方法或函数 basenameSplFileInfo::getBasename() 获取他们,区别在于是否摘除指定的 $suffix 后缀。

  • 3.5 示例

<?php $filename = &#39;F:\Program Files\SSH Communications Security\SSH Secure Shell\Output.txt&#39;;


$file = new SplFileInfo($filename);

// 目录路径
$directory1 = pathinfo($filename, PATHINFO_DIRNAME);
$directory2 = dirname($filename);
$directory3 = $file->getPath();

echo '--- directory begin: ---' . PHP_EOL;
echo $directory1 . PHP_EOL, $directory2 . PHP_EOL, $directory3 . PHP_EOL;

// 文件名
$suffix = '.txt';
$filename1 = pathinfo($filename, PATHINFO_FILENAME);
$filename2 = basename($filename, $suffix);
$filename3 = $file->getBasename($suffix);

echo '--- filename begin: ---' . PHP_EOL;
echo $filename1 . PHP_EOL, $filename2 . PHP_EOL, $filename3 . PHP_EOL;

// 扩展名
$extension1 = pathinfo($filename, PATHINFO_EXTENSION);
$extension2 = $file->getExtension();

echo '--- extension begin: ---' . PHP_EOL;
echo $extension1 . PHP_EOL, $extension2 . PHP_EOL;

// basename = 文件名 + 扩展名
$basename1 = pathinfo($filename, PATHINFO_BASENAME);
$basename2 = basename($filename);
$basename3 = $file->getBasename();
$basename4 = $file->getFilename();

echo '--- basename begin: ---' . PHP_EOL;
echo $basename1 . PHP_EOL, $basename2 . PHP_EOL, $basename3 . PHP_EOL, $basename4 . PHP_EOL;

它们的运行结果如下:

--- directory begin: ---
F:\Program Files\SSH Communications Security\SSH Secure Shell
F:\Program Files\SSH Communications Security\SSH Secure Shell
F:\Program Files\SSH Communications Security\SSH Secure Shell
--- filename begin: ---
Output
Output
Output
--- extension begin: ---
txt
txt
--- basename begin: ---
Output.txt
Output.txt
Output.txt
Output.txt
  • 3.6 Detaillierte Einführung in das PHP-Dateisystem图Detaillierte Einführung in das PHP-Dateisystem

另外需要注意的一点是在使用 SplFileInfo 获取 basename 时,getBasename() 和 getFilename() 返回基本一致,但是在处理根目录下的文件名获取时表现稍有不同。
这里可以到官方文档中用户 提交的反馈 去详细了解一下。
  • 4 获取文件的绝对路径

绝对路径由 realpath($path)SplFileInfo::getRealpath() 获取。

  • 5 获取文件类型

可以使用 filetype($filename)SplFileInfo::getType() 来获取文件的类型。

返回值范围:

  • dir

  • file

  • char

  • fifo

  • block

  • link

  • unknown

可以查看 Linux 文件类型与扩展名 相关文件类型,这里我们重点关注下 dir 目录和 file 普通文件类型即可。

  • 6 获取文件大小

可以使用 filesize($filename)SplFileInfo::getSize() 来获取文件的大小,不再赘述。

  • 7 获取文件权限

可以使用 fileperms($filename)SplFileInfo::getPerms() 来获取到文件的所属权限。

值得注意的是它们的返回值是十进制表示的权限,如果需要获取类似 0655 八进制权限表示法,我们需要对返回值进行处处理才行:

// @see  http://php.net/manual/zh/function.fileperms.php#refsect1-function.fileperms-examples
$permissions = substr(sprintf("%o", fileperms($filename)), -4);

你可以通过 PHP: fileperms() values and convert these 了解更多关于 PHP 获取文件权限转换的更多细节。

基本上学习完这些文件元数据信息获取方法,差不多可以应对日常开发过程中的多数应用场景,尽管如此,还是建议仔细去阅读官方 文件系统函数,那里才是知识的源泉。

掌握文件的元数据,对我们了解文件的特性大有裨益,就好比两个人谈恋爱,懂得彼此才是最好的状态。

2.2 文件系统操作

可以说我们日常在处理文件的过程中,更多的是在操作文件或者目录(文件夹),本节我们将学习文件系统操作相关知识。

依据文件类型的不同我们可以简单的将操作分为:

  • 对目录(dir)的操作

  • 和对普通文件(file)的操作

2.2.1 目录操作使用场景

在处理目录时我们一般涉及如下处理:

  1. 创建目录

  2. 删除目录

  3. 打开目录

  4. 读取目录

  5. 关闭目录句柄

  • 场景一

我们有一套 CMS 管理系统支持文件上传处理,当目录不存在时依据文件上传时间,动态的创建文件存储目录,比如,我们依据 年/月/日(2018/01/01) 格式创建目录。这里就涉及到 目录创建 的处理。

  • 场景二

当然,文件上传完成了还不够,我们还需要读取各个目录下的所有文件。这里涉及 打开目录读取目录 以及读取完成后 关闭目录句柄

有了相关概念和思路后,我们具体看看究竟 PHP 文件系统给我们提供了哪些方便处理目录的函数呢?

2.2.1.1 创建目录

在 PHP 文件系统扩展中同样给我们提供了处理 目录结构的系统函数。

其中创建一个新目录需要使用 [mkdir($pathname [, $mode = 0777, $recursive = false])](http://php.net/manual/zh/func... 函数。

  1. $pathname 参数为待创建目录的路径

  2. $mode 为创建目录时的访问权限,0777 意味着获取最大访问权限

  3. $recursive 用于标识是否递归创建目录,默认 false 不会递归创建

请看一个示例:

$pathname = "/path/to/your/upload/file/2018/01/01";
$created = mkdir($pathname);

创建目录是不是特别的简单呢?

但是等等,我们在类 Unix 系统中满心欢喜的使用 mkdir 并采用 $mode=0777 权限来创建一个全新的目录,但为什么当我们进入到目录中看到的目录的权限却是 0755 呢?

umask 掩码

这里涉及到 umask 掩码的问题!

重点: 原来我们在类 Unix 系统中创建新目录是给出的权限会默认减去当前系统的 umask 值,才是实际创建目录时的所属权限。

什么意思呢?

比如:

// 我们期望创建的文件权限
$mode = 0777;

// 当前系统中 umask 值
$umask = 0022;// 可以由 umask 命令查看当前系统 umask 值,默认是 0022

// 实际创建的文件权限
  0777
- 0022
------
= 0755

现在我们来对之前的实例稍作修改,看看 PHP 如何创建目录时得到希望的系统权限吧:

$pathname = "/path/to/your/upload/file/2018/01/01";

// 将系统 umask 设置为 0,并取得当前 umask 值(比如默认 0022)
$umask = umask(0);
$created = mkdir($pathname, $mode = 0777);
// 将系统 umask 设置回原值
umask($umask);

有关 umask 函数说明可以查看官方手册。另外可以查看 Why can't PHP create a directory with 777 permissions? 这个问答了解更多细节。

2.2.1.2 目录遍历

面向过程的目录遍历提供两种解决方案:

  1. 通过 opendir、readdir 和 closedir 来遍历目录;

  2. 另一种是直接使用 scandir 遍历指定路径中的文件和目录。

目录遍历示例一,出自 官方文档:

<?php $dir = "/etc/php5/";

// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
    if ($dh = opendir($dir)) {
        while (($file = readdir($dh)) !== false) {
            echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
        }
        closedir($dh);
    }
}

// 输出结构类似于:
// filename: . : filetype: dir
// filename: .. : filetype: dir
// filename: apache : filetype: dir
// filename: cgi : filetype: dir
// filename: cli : filetype: dir
?>

目录遍历示例二,出自 官方文档:

<?php $dir    = &#39;/tmp&#39;;
$files1 = scandir($dir);

print_r($files1);

// 输出结构类似于:
// Array
// (
//     [0] => .
//     [1] => ..
//     [2] => bar.php
//     [3] => foo.txt
//     [4] => somedir
// )

目录的操作处理大致就是在处理这两类问题,相比于普通文件的处理来讲简单很多,下一节我们会学习有关普通文件的处理,请大家做好战斗准备。

2.2.2 文件操作使用场景

可以说我们在处理文件系统时,绝大多数都是在处理一个普通文件,那么我们在操作文件时,我们究竟在做什么呢?

你可能已经想到了,没错我们多数时候就是在处理如下文件问题:

  • 创建一个新的空文件

  • 打开一个文件句柄,以供后续读取或写入

  • 将文件中的内容覆盖掉(覆盖写入),或者在文件末尾写入新的内容(追加写入)

  • 读取文件的内容

  • 删除文件

  • 复制文件

  • 关闭文件句柄

文件的读取和写入相对会复杂一些,所以这两部分的内容会在稍后详细讲解。先让我们看看其它几个常见文件处理。

2.2.2.1 创建空文件

创建空文件有两种方式:
一是:以写入(w)模式使用 fopen($filename, $mode = 'wb') 打开一个文件,当文件不存在时则会创建一个新文件;
二是:使用 touch 函数创建一个新文件。

这两个函数同其它文件系统函数使用大致相同,感兴趣的朋友可以阅读手册,这里不作展开。

2.2.2.2 删除文件

删除文件由 unlink($filename) 函数完成。

2.2.2.3 复制文件

复制文件由 copy($source, $dest) 函数完成,会将 $source 文件拷贝到 $dest 文件中。

如果需要移动文件(重命名)可以使用 rename($oldname, $newname) 完成这个处理。

以上都是相对简单的文件处理函数就不一一举例说明了。

接下来学习如何读取文件中的内容。依据二八原则,可以说我们百分之八十的时间都在处理文件写入和读取的处理,所以我们有必要理清如何对文件进行读取和写入。

2.2.2.4 读取文件

读取文件的标准流程是:

    1. 打开一个文件句柄;

    2. 使用文件读取函数读取文件;

    3. 判断是否到文件结尾,到结尾则结束读取,否则回到操作 2;

    4. 读取完成关闭句柄;

    开始之前我们需要准备一个有数据的文件,比如 F:\php_workspace\php-code-kata\read.txt,在看一个简单的文件读取示例:

    <?php // 这里为了贴合读取文件的标准流程,使用 do{} while 语句,你也可以修改成 while 语句。
    
    
    $filename = "F:\\php_workspace\\php-code-kata\\read.txt";
    
    // 1. 打开一个文件句柄;
    $handle = fopen($filename, $mode = &#39;rb&#39;);
    
    do {
        // 2. 使用文件读取函数读取文件;
        $content = fgetc($handle);
        echo $content;
    
        // 3. 判断是否到文件结尾,到结尾则结束读取,否则回到操作 2;
    } while (!feof($handle));
    
    // 4. 读取完成关闭句柄;
    fclose($handle);
    
    // 读取显示大致类似:
    // hello world!

    现在,我们来详细讲解一下上述代码做了什么处理吧:

    • 使用 fopen($filename, $mode) 打开一个文件或 URL 句柄,供后续文件系统函数使用;

    • 使用 fgetc($handle) 函数从文件句柄中读取一个字符;

    • 使用 feof($handle) 判断文件句柄是否到文件的结尾处,否则继续读取文件;

    • 当读取完成后使用 fclose($handle) 关闭打开的文件句柄,完成文件读取的所有操作。

    总体来说,在读取文件时按照以上处理流程,基本上太容易出错的。不过即便如此,还是有些重点需要我们小心处理:

    • 我们以什么模式打开一个文件句柄,示例中使用 $mode='rb' r(read) 只读模式开个一个文件句柄(只读模式下不能对文件尽心写入)。另外还有几个常用模式可供使用:

      • r+        读写模式

      • w(write)  覆盖写入

      • w+        覆盖读写

      • a(append) 追加写入

      • a+        追加读写

      • b     重点关注此模式,为增强项目可移植和健壮性,推荐所有模式添加「b」模式强制使用二进制模式

      • 有关所有可用模式的说明可以从 模式 手册中查找。

    • 在执行文件内容读取时除了逐字符读取(fgetc),要支持一下集中读取形式:

      • fgets($handle)   每次读取一行数据

      • fgetss($handle)  每次读取一行数据,并过来 HTML 标记

      • fgetcsv($handle) 读取 CSV 文件,每次读取一样并解析字段

      • fread($handle, $length)   每次从句柄中最多读取 $length 个字节。

    • 处理可以从句柄中读取文件数据,PHP 还提供将整个文件读取的方法:

      • file($filename)        把整个文件读入一个数组中

      • file_get_contents($filename) 将整个文件读入一个字符串

    注意: 读取文件操作时我们推荐使用 file_get_contents

    到这里我们基本上就涵盖了文件读取的所有知识点,相信大家对文件读取已经有了一个比较系统的认知。

    下面我们进入到文件写入处理中,看看文件写入的正确姿势。

    2.2.2.5 读取写入

    典型的文件写入流程基本上和文件读取流程一致:

      1. 打开一个文件句柄;

      2. 使用文件读取函数向文件中写入内容;

      3. 写入完成关闭句柄。

      依据惯例我们来看一个简单的示例:

      <?php $filename = "F:\\php_workspace\\php-code-kata\\read.txt";
      
      // 1. 打开一个文件句柄;
      $handle = fopen($filename, $mode = &#39;ab&#39;);
      
      // 2. 使用文件读取函数向文件中写入内容
      fwrite($handle, "hello filesystem to write!\n");
      
      // 3. 写入完成关闭句柄;
      fclose($handle);
      注意:这里我们以追加写入的模式 $mode = 'ab' 写入文件内容。

      文件写入就如同文件读取一样的简单,相信大家能够轻松掌握这方面的知识。然而,我们显示世界可能充满了荆棘,稍不留神可能就会深陷泥沼。比如:

      • 我在写入文件时,同时其他人也在对同一个文件进行写入,怎么办?我们可以使用 flock($handle, LOCK_EX) 加锁函数进行独占写入。

      • 每次都需要 打开文件写入再关闭 是在麻烦!有没有更简单的方式写文件呢?PHP 同样为你考虑到了这点,所以提供了 [file_put_contents($filename, $data [, LOCK_EX])](http://php.net/manual/zh/func... 将一个字符串写入文件,同样的它也支持独占写入。

      到这里,我们基本上就学习完 PHP 文件系统中大多数常用的函数了。然而就如我所说的那样,现实世界总是残酷的。尤其是在读写文件时,经常会遇到各种各样的错误,我们应该如何才能避免呢?

      嗯,PHP 一样为我们内置了检测文件有效性的函数,规避各种错误。

      2.2.2.5 如何处理文件权限及检测有效性
      • 文件有效性检测

      检测文件的有效性能够让我们规避常见的开发错误,比如:

      1. 当相文件中写入数据时,是不是需要检测它有可写的权限,并且它是不是一个文件而非文件夹?

      2. 读取文件内容时,是不是需要查看下我们能不能对其进行读取?

      3. 在安装项目时,我们是不是需要检测已经依据实例配置文件创建了实际的配置文件呢?

      这些内容都需要使用到文件有效性检测相关知识。

      1. 判断文件是否可写我们有:is_writable($filename) 和 SplFileInfo::isWritable()

      2. 路径目录判断:is_dir($filename)](http://php.net/manual/zh/function.is-dir.php) 和 **[SplFileInfo::isDir()](http://php.net/manual/zh/splfileinfo.isdir.php)**;文件判断:[is_file($filename) 和 **SplFileInfo::isFile()。

      3. 检测文件或目录是否已经创建过,我们使用 file_exists($filename) 函数完成。

      • 如何修改文件权限

      当我们能够正确的检测文件是否存在时,我们还需要面对的问题时,如果我们的文件当前用户 不可写入,我们应该如何修改权限使其可写呢?

      这里就涉及修改文件权限操作,之前我们在创建目录是已经接触过 umask 掩码相关知识。这里我们将讲解那些已经创建的文件权限变更的方法。

      通常,我们会使用 chmod($filename, $mode) 去修改一个文件的权限。

      另外,还可以关注以下几个权限相关的处理函数:

      • chgrp($filename, $group) 改变文件所属的组

      • chown($filename, $user) 改变文件的所有者

      以及,之前提到过的 umask 修改掩码函数。

      文章进行到这里,其实基本上 PHP 文件系统的所有知识都已经涉及到了。那么,下回见吧?不不不...

      为了应对实战(面试需要),我们可能需要进一步对目录遍历做更进一步的研究。还记得我们之前使用过 scandir 来遍历指定路径中的文件和目录夹么?

      现在我们将使用面向对象的接口来重新实现一个权限的目录遍历处理。

      3 面向对象的目录遍历

      使用面向对象的接口来遍历目录,是一个非常有意义的教程,这里我们所涉及使用的接口包括:

      • DirectoryIterator 创建非递归的目录迭代器

      • RecursiveDirectoryIterator 创建递归的目录迭代器

      • RecursiveIteratorIterator 创建一个递归迭代器的迭代器(用于迭代获取 RecursiveIteratorIterator 示例)

      话不多说,我们看下如何创建一个功能强大的支持递归迭代的目录迭代程序:

      /**
       * 目录扫描
       * 
       * @method listContents($path, $recursive = false) 获取目录中所有文件及文件夹
       */
      class DirectoryScanner 
      {
      
          /**
           * 获取目录中所有文件及文件夹
           * 
           * @param $path      目录
           * @param $recursive 递归获取
           * 
           * @return array
           */
          public static function listContents($path, $recursive = false)
          {
              $iter = $recursive ? static::getRecursiveDirectoryIterator($path) : static::getDirectoryIterator($path);
      
              $result = [];
              foreach ($iter as $file) {
                  if (in_array($file->getFilename(), ['.', '..'])) {
                      continue;
                  }
      
                  $result[] = clone $file;
              }
      
              return $result;
          }
      
          /**
           * 获取目录迭代器
           * 
           * @param $path      目录
           * 
           * @return DirectoryIterator::class
           */
          public static function getDirectoryIterator($path)
          {
              return new DirectoryIterator($path);
          }
      
          /**
           * 获取递归目录迭代器
           * 
           * @param $path      目录
           * @param $mode      遍历模式: RecursiveIteratorIterator::SELF_FIRST 从当前目录开始遍历;RecursiveIteratorIterator::CHILD_FIRST 从子目录开始遍历
           * 
           * @return RecursiveIteratorIterator::class
           */
          public static function getRecursiveDirectoryIterator($path, $mode = RecursiveIteratorIterator::SELF_FIRST )
          {
              return new RecursiveIteratorIterator(
                  new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
                  $mode
              );
          }
      }
      
      $path = 'F:\php_workspace\php-code-kata\direcotry-iterator\dir';
      
      var_dump(DirectoryScanner::listContents($path));
      var_dump(DirectoryScanner::listContents($path, true));

      4 PHP 文件系统思维导图

      文件系统思维导图Detaillierte Einführung in das PHP-Dateisystem

      相关推荐:

      php中导出大量数据的实现方法

      PHP如何使用某个键值对二维数组排序

      PHP开发中redis的主从模式以及加密方法

      Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in das PHP-Dateisystem. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

      Stellungnahme:
      Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn