我目前正在写一个记录器,该记录器为某些插件在ILIAS中写入相当大的日志文件。我正在使用整洁的新文件系统。由于新的日志消息需要追加到文件中,因此我不能简单地使用put或update,因为它们似乎总是截断日志文件。 Flysystem似乎不支持简单的附加命令,所以我发现一种可行的方法如下:
$old_data = "";
if ($DIC->filesystem()->storage()->has($this->path)) {
$old_data = $DIC->filesystem()->storage()->read($this->path);
}
$DIC->filesystem()->storage()->put($this->path, $old_data.$string);
但是,如果将大量数据添加到日志中,那么对于IO而言,这似乎非常昂贵。我想,最好是使用流来完成。在文档(https://github.com/ILIAS-eLearning/ILIAS/tree/release_5-3/src/Filesystem)中,我发现了以下内容:
$webDataRoot = $DIC->filesystem()->web();
$fileStream = $webDataRoot->readStream('relative/path/to/file');
//seek at the end of the stream
$fileStream->seek($fileStream->getSize() - 1);
//append something
$fileStream->write("something");
但是,与此同时,我收到了无法写入不可写流异常。看来,我需要像这样打开流:
$resource = fopen('myPath', 'rw');
但是在文档中特别不建议这样做。通过使用ILIAS中的文件系统解决此问题的最佳方法是什么?
答案 0 :(得分:3)
问题
ILIAS的文件系统抽象利用flysystem来操纵文件系统。但是,正如您已经指出的那样,flysystem没有提供将数据追加到文件的简便方法。主要原因似乎似乎是这样的事实:由于底层技术,许多用于将文件写到存储后端的文件系统适配器都不支持追加操作,例如S3 V3 storage adapter,它重新上传了整个文件。文件。
不幸的是,位于(https://github.com/ILIAS-eLearning/ILIAS/tree/release_5-3/src/Filesystem)的文档是错误的,因为只有某些文件系统适配器仅“模仿”文件流的行为,flysystem返回的流才是只读的。该流指向本地副本或内存流,而不是位于存储后端的“真实”文件,请参见Flysystem AWS S3 Adapter。
结论
总而言之,没有使用当前ILIAS文件系统实现将数据追加到现有文件的正确方法,因为flyway不提供此类操作。 此外,即使flyway提供了某些存储后端,它们仍将不支持此类操作。一个很好的例子是AWS S3存储后端,请参见问题41783903的答案。
您的用例可能的解决方法
如果能够使用多个日志文件,请使用某种日志文件轮换来减少IO,这不是解决方案,但有助于将负载至少保持在一致的水平。例如,如果大小超过20MB,则写入一个新的日志文件,并保留最后20个日志文件。