使用PHP解析大型文本文件而不杀死服务器

时间:2009-08-10 14:19:08

标签: php memory parsing

我正在尝试阅读一些大文本文件(介于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)。我认为这是阅读大文件最有效的内存方式。是否有一些我遗漏的方法对内存更有效?也许有些设置会在收集时将内容保存在内存中?

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

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

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

  1. unset $buffer完成将其写入磁盘后,明确告知GC清理它。
  2. if块放在另一个函数中,以便GC在该函数退出时运行。
  3. 这些建议背后的原因是我怀疑垃圾收集器没有释放内存,因为一切都是在单个函数内完成的,而且GC是垃圾。

答案 2 :(得分:0)

我希望在许多情况下这会失败。您正在读取4096字节的块。谁知道截止时间不会在<text>的中间?在这种情况下,您的str_replace将无效。

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