wpjscc/filesystem

异步文件系统抽象。

v0.2.0 2023-08-26 09:49 UTC

This package is auto-updated.

Last update: 2024-08-25 10:53:15 UTC


README

CI status

ReactPHP 的文件系统组件,支持非阻塞文件系统操作。

开发版本:此分支包含即将发布的 0.2 版本的代码,这将为本包的未来发展指明方向。

有关详细信息,请参阅安装说明

目录

快速入门示例

以下是一个列出当前目录中所有内容的程序。

use React\Filesystem\Factory;
use React\Filesystem\Node\DirectoryInterface;
use React\Filesystem\Node\NodeInterface;

Factory::create()->detect(__DIR__)->then(function (DirectoryInterface $directory) {
    return $directory->ls();
})->then(static function ($nodes) {
    foreach ($nodes as $node) {
        assert($node instanceof NodeInterface);
        echo $node->name(), ': ', get_class($node), PHP_EOL;
    }
    echo '----------------------------', PHP_EOL, 'Done listing directory', PHP_EOL;
}, function (Throwable $throwable) {
    echo $throwable;
});

有关示例,请参阅示例

使用

请参阅Factory::create()

工厂

Factory 类存在是为了方便选择最佳可用的 文件系统实现

create()

可以使用 create(): AdapterInterface 方法创建一个新的文件系统实例

$filesystem = \React\Filesystem\Factory::create();

此方法始终返回一个实现 adapterinterface 的实例,实际的 文件系统实现 是一个实现细节。

此方法可以随时调用。但是,某些调度机制会被使用,这将使事件循环因为每个新的文件系统适配器实例而变得繁忙。为了避免这种情况,建议您只创建一次,并在需要的地方注入它。

文件系统实现

除了 FilesystemInterface 之外,还提供了一系列文件系统实现。

所有文件系统都支持以下功能

  • 声明节点
  • 列出目录内容
  • 从文件中读取/写入

对于此包的大多数消费者来说,底层文件系统实现是一个实现细节。您应该使用 Factory 来自动创建新实例。

工厂将确定您环境中最有效的文件系统。任何基于扩展的文件系统都优先于性能较差的文件系统。当未检测到任何扩展时,它将回退到使用阻塞系统调用的内部回退文件系统。因此,强烈建议安装一个扩展,以解锁更高效的文件系统操作。

高级!如果您明确需要某个文件系统实现,可以手动实例化以下类之一。请注意,您可能必须首先安装相应事件循环实现的必需 PHP 扩展,否则它们在创建时会抛出 BadMethodCallException

Eio

基于 ext-eio 的文件系统。

此文件系统使用 eio PECL 扩展,它提供了对 libeio 库的接口。

已知此文件系统与 PHP 7+ 兼容。

Uv

基于 ext-uv 的文件系统。

该文件系统使用了uv PECL扩展,该扩展提供了一个访问libuv库的接口。

已知此文件系统与 PHP 7+ 兼容。

AdapterInterface

detect()

推荐使用detect(string $path): PromiseInterface方法来获取表示文件系统上节点的对象。

调用此方法时,它会尝试检测提供的路径是哪种类型的节点,并返回一个实现NodeInterface的对象。如果给定路径不存在,将返回一个NotExistInterface对象,您可以使用该对象创建文件或目录。

directory()

directory(string $path): DirectoryInterface方法创建一个表示指定路径上的目录的对象。

请注意,与detect方法不同,directory方法不能保证您传递的路径在文件系统中实际是一个目录,可能会导致意外的行为。

file()

file(string $path): DirectoryInterface方法创建一个表示指定路径上的文件的对象。

请注意,与detect方法不同,file方法不能保证您传递的路径在文件系统中实际是一个文件,可能会导致意外的行为。

NodeInterface

NodeInterface是所有其他节点接口(如FileInterfaceDirectoryInterface)的核心。它提供了对所有类型节点都很有用的基本方法。

path()

path(): string方法返回节点位置的路径部分。因此,如果完整路径是/path/to/file.ext,则此方法返回/path/to/

name()

name(): string方法返回节点位置的名称部分。因此,如果完整路径是/path/to/file.ext,则此方法返回file.ext

stat()

stat(): PromiseInterface方法对节点进行统计并提供有关其大小、完整路径、创建/更新时间等信息。

DirectoryInterface

ls

ls(): PromiseInterface>>方法列出给定目录的所有内容,并返回一个包含节点数组的数组。它将尽可能检测节点的类型,否则将回退到FilesystemInterface::detect(string $path): PromiseInterface

FileInterface

该接口上的*Contents方法旨在尽可能与PHP的file_(get|put)_contents函数的行为一致。结果是一个非常熟悉的API,可以用于从文件中读取/流式传输,或将内容写入/追加到文件。

getContents

对于从文件读取,getContents(int $offset = 0, ?int $maxlen = null): PromiseInterface提供了两个参数,用于控制从文件中读取的数据量。如果没有参数,则读取全部内容。

$file->getContents();

偏移量和最大长度允许您“选择”要读取的文件的一部分。下面的示例将跳过前2048个字节,然后从文件中读取最多1024个字节。然而,如果文件在2048偏移量之后只包含512个字节,它将只返回这些512个字节。

$file->getContents(2048, 1024);

可以使用定时器作为触发器来检查更新来跟踪文件。

$offset = 0;
Loop::addPeriodicTimer(1, function (TimerInterface $timer) use ($file, &$offset, $loop): void {
    $file->getContents($offset)->then(function (string $contents) use (&$offset, $timer, $loop): void {
        echo $contents; // Echo's the content for example purposes
        $offset += strlen($contents);
    });
});

putContents

向文件写入是putContents(string $contents, int $flags = 0): PromiseInterface的特例。默认情况下,当传递内容时,如果文件存在,则截断文件;如果不存在,则创建一个新文件并将其填充给定的内容。

$file->putContents('ReactPHP');

支持向文件追加,使用\FILE_APPEND常量,如果文件存在,则将其追加。

$file->putContents(' is awesome!', \FILE_APPEND);

NotExistInterface

两种创建方法都会检查父目录是否存在,如果不存在,则创建它。这实际上使创建过程递归。

createDirectory

以下示例将创建lets/make/a/nested/directory作为递归目录结构。

$filesystem->directory(
    __DIR__ . 'lets' . DIRECTORY_SEPARATOR . 'make' . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'directory'
)->createDirectory();

createFile

以下操作将在lets/make/a/nested/directory目录中创建with-a-file.txt文件,并将This is amazing!写入该文件。

use React\Filesystem\Node\FileInterface;

$filesystem->file(
    __DIR__ . 'lets' . DIRECTORY_SEPARATOR . 'make' . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'directory' . DIRECTORY_SEPARATOR . 'with-a-file.txt'
)->createFile()->then(function (FileInterface $file) {
    return $file->putContents('This is amazing!')
});

安装

推荐使用Composer安装此库。如果您是Composer的新用户,请参阅Composer入门指南

一旦发布,该项目将遵循SemVer。目前,这将安装最新的开发版本。

composer require react/filesystem:^0.2@dev

有关版本升级的详细信息,请参阅变更日志

该项目旨在在任何平台上运行,因此不需要任何PHP扩展,并支持从PHP 7.4到当前PHP 8+的运行。强烈建议使用该项目支持的最新PHP版本。

建议安装事件循环扩展,但这完全是可选的。有关更多详细信息,请参阅事件循环实现

测试

要运行测试套件,首先需要克隆此仓库,然后通过Composer安装所有依赖项。

composer install

要运行测试套件,请转到项目根目录并运行

vendor/bin/phpunit

许可证

MIT许可,请参阅LICENSE文件