如何在PHP开头截断文件?

Foo*_*Bar 5 php logging truncate file filesize

我有一个用 PHP 编写的简单记录器类。它写入的文件应该具有最大大小。我知道我可以用 截断文件ftruncate($filename, $size),但这会在最后删除内容。所以我想做的是以下内容:

if(filesize($filename) > $mySize) {
  //remove X bytes at BEGINNING of $filename
}

// append log message
$handle = fopen($filename, 'a+');
if($handle !== false) {
  fwrite($handle, $myMessage);
  fclose($handle);
}
Run Code Online (Sandbox Code Playgroud)

这样日志会随着时间的推移“滚动”文件,而不是无限增长(最终崩溃到 2GB,这signed int是 PHP的限制)。

删除文件开头而不必担心性能的最佳方法是什么?我认为将文件逐行读入另一个缓存文件很慢,特别是如果日志记录发生得相当频繁。有没有更好的办法?

Ric*_*ers 0

我过去对这种简单记录器采取的方法是采用标准记录大小。然后,我使用该标准记录大小以及记录索引来计算写入日志记录的文件偏移量。

通常我使用第一条记录来包含当前记录索引,即放置下一条记录的位置,后跟逗号,然后是最大记录数。

所以基本逻辑是

  • 检查日志文件是否存在,如果不存在则初始化记录索引和最大索引值
  • 添加记录时,读取第一条记录以获取当前索引和最大索引
  • 计算文件偏移量并fseek()写入该点并写入记录
  • 将当前索引增加到fseek()第一条记录并更新索引记录
  • 关闭文件

最重要的是要有一个完整的、适当大小的空格或空白填充记录,以便所有记录偏移量对齐,并且当您使用文本编辑器查看文件时,它都是文本。还要确保记录末尾有一个新行,以便于查看,并且每个记录在文本查看器(无论是编辑器还是其他应用程序(例如 Web 浏览器))中都在新行上。

最后,作为增量的一部分,执行一个模数来强制翻转,因为您希望它成为一个循环缓冲区。只需确保添加一个,因为您希望索引从 1 到 n(其中 n 是最大记录数),因为记录 0(第一条记录)用于包含当前索引和最大记录数。

有关使用 PHP 打开、查找、写入和关闭文件的机制,请参阅PHP 从特定位置附加到文件