【问题标题】:Parsing Large Text Files with PHP Without Killing the Server使用 PHP 解析大文本文件而不杀死服务器
【发布时间】:2009-08-10 14:19:07
【问题描述】:

我正在尝试读取一些大型文本文件(50M-200M 之间),进行简单的文本替换(基本上我所拥有的 xml 在一些常规情况下没有被正确转义)。这是该函数的简化版本:

<?php
function cleanFile($file1, $file2) {
$input_file     = fopen($file1, "r");
$output_file    = fopen($file2, "w");
  while (!feof($input_file)) {
    $buffer = trim(fgets($input_file, 4096));
    if (substr($buffer,0, 6) == '<text>' AND substr($buffer,0, 15) != '<text><![CDATA[')
    {
      $buffer = str_replace('<text>', '<text><![CDATA[', $buffer);
      $buffer = str_replace('</text>', ']]></text>', $buffer);
    }
   fputs($output_file, $buffer . "\n");
  }
  fclose($input_file);
  fclose($output_file);     
}
?>

我没有得到的是,对于最大的文件,大约 150mb,PHP 内存使用量在失败之前超出了图表(大约 2GB)。我认为这是读取大文件的最节省内存的方法。是否有一些我错过的方法对记忆更有效?也许某些设置在应该收集时将其保存在内存中?

换句话说,它不工作,我不知道为什么,据我所知,我没有做错事。我有什么方向可以走吗?感谢您的任何意见。

【问题讨论】:

标签: php memory parsing


【解决方案1】:

PHP 并不是为此而设计的。将工作卸载到不同的进程并调用它或从 PHP 启动它。我建议使用PythonPerl

【讨论】:

  • 很遗憾,此时无法选择其他语言。 :(
  • 然后在一个单独的进程中使用 PHP 进行。关键是您不应该将该大文件作为请求的一部分进行解析。您应该在单独的进程中卸载工作,返回响应,然后允许第二个请求来确定进程 ID 是否完成。异步 FTW。
  • 同意。我的猜测是您正在通过 ftp、批处理等方式接收文件。为什么不在文件到达文件系统时立即解析文件,而不是等待有人从 Web 请求中将其拉下来。
  • 呵呵.. 刚刚注意到错字...我的意思是“进程 is 完成”而不是“进程 ID 完成”。 :D
【解决方案2】:

根据我对 PHP 垃圾收集的了解,以下内容可能会有所帮助:

  1. unset$buffer 当你完成将其写入磁盘时,明确告诉 GC 清理它。
  2. if 块放入另一个函数中,以便在该函数退出时运行 GC。

这些建议背后的原因是我怀疑垃圾收集器没有释放内存,因为一切都在一个函数中完成,而 GC 就是垃圾。

【讨论】:

  • 试过这个。它确实释放了一些内存,但还不够。我希望我知道它究竟对记忆做了什么。
【解决方案3】:

我希望这在很多情况下都会失败。您正在读取 4096 字节的块。谁知道截止不会在&lt;text&gt; 的中间?在这种情况下,您的 str_replace 将不起作用。

您是否考虑过使用正则表达式?

【讨论】:

    猜你喜欢
    • 2012-06-21
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2020-11-16
    • 2015-05-04
    相关资源
    最近更新 更多