【问题标题】:PHP to read & parse big sized file? [closed]PHP读取和解析大文件? [关闭]
【发布时间】:2012-08-27 12:46:29
【问题描述】:

我要读取一个大小为 200Mb 的文本文件,然后在其中编辑一些内容,然后将其保存回来。但我有错误。所以:

  • 应该在 php 中修改哪些具体设置?

还有什么文件读取方法最适合打开和解析大文件?我的意思是:

  • fread ?
  • file_get_contents ?

【问题讨论】:

  • 你遇到了什么错误?他们将大大有助于解决您的问题。
  • 你真的需要内存中的整个文件来解析它吗?如果没有,请使用fread() 一次读取一行或几行,使用fwrite() 写入另一个(修改过的)文件。
  • 您是否尝试过使用fgets 分块读取文件?
  • fread 如果您明智地使用它,它将起作用,您可以创建一个循环并仅读取其中的一小部分,直到到达文件末尾 (php.net/manual/en/function.fread.php) 。保存后,您可以使用 fwrite 来完成。
  • 你的脚本应该对文本文件做什么,提供更多细节。

标签: php file memory file-get-contents fread


【解决方案1】:

我不得不做类似的事情,读取 1GB 的文件。我想留在 PHP 中,所以最后我使用fread 一点一点地读取文件的部分内容:

while (!feof($source_file)) {
    $buffer = fread($source_file, 1024);  // use a buffer of 1024 bytes
    $buffer = str_replace($old,$new,$buffer);
    fwrite($target_file, $buffer);
}

这样,在任何给定时间,只有一小部分文件保存在内存中。我检查了效率 很好,整个文件大约半分钟。

一个小提示——如果被替换的字符串位于缓冲区的末尾,它可能不会被替换。为确保您更改了所有出现的位置,再次以较小的偏移量运行脚本:

$buffer = fread($source_file, 512);
fwrite($target_file, $buffer);  
while (!feof($source_file)) {
    $buffer = fread($source_file, 1024);  // use a buffer of 1024 bytes
    $buffer = str_replace($old,$new,$buffer);
    fwrite($target_file, $buffer);
}

【讨论】:

  • 如果您的搜索字符串超过一个字符,这将不会总是有效 :)
  • 再次运行算法不是一个好选择,最好知道最大搜索字符串的长度并保留前一个缓冲区的那部分,附加另一个段等。
  • @Jack,你又是对的 :) 我知道.... 写完这个脚本后,我在 1GB 文件上运行它,只用了不到 1 分钟。所以是的,我可以按照你说的那样做,而且会花费更少的时间,但是这 30 秒并没有那么重要。如果效率比是的更重要,那么你是完全正确的。 +1
  • @Ja͢ck - 很高兴知道这不是一个好选择。但是您有建议的方法吗?
  • @mikoop 它在上面的评论中解释过......如果您的搜索字符串长 10 个字节,那么在第二个循环之前,您从缓冲区末尾保留 9 个字节并将其用作起始字节然后是文件中接下来的 X 个字节,等等。
【解决方案2】:

与已经存在的答案基本相同,但带有文件指针。

$original = fopen("/tmp/inputfile.txt", "r");
$new = fopen("/tmp/outputfile.txt", "w");
if ($original && $new) {
    while (($buffer = fgets($handle)) !== false) {
        //do modification on $buffer (which is a single line)

        fwrite($new, $buffer);
    }

    fclose($original);
    fclose($new);
}

【讨论】:

    【解决方案3】:

    我使用以下方法完成了类似的任务:

    $file = file_get_contents("/path/to/file");
    $lines = explode("\n", $file);
    
    $arr = preg_grep("/search_string/", $lines);
    
    // $arr is now a smaller array of things to match
    // do whatever here
    
    // write back to file
    file_put_contents("/path/to/file", implode("\n", array_merge($arr, $lines)));
    

    【讨论】:

    • 这不会遭受与 OP 相同的内存问题吗?
    【解决方案4】:

    PHP 并非设计或打算这样做。您可能需要考虑使用 Perl,或者将文本更改为 XML,或者将其放入数据库中。

    按照您想要的方式执行此操作意味着整个文件将被加载到内存中。如果你有多个用户在做同样的事情,你会很快耗尽内存。

    XML解析看这里XMLReader

    【讨论】:

    • 一方面,您可以将任何旧文本文件转换为 XML 并不一定有意义。我们不知道文本文件的来源或它们包含的内容,因此如果必须使用 PHP 脚本动态完成(如果我们能够读取文件),将它们放入数据库也不一定是一种选择这样做,问题已经解决了)。
    • @WesleyMurch 用 PHP 处理这么大的文件也没有意义。 OP 从未指定它必须是文本文件。我只是指出更好的选择。我不明白为什么这会被否决。如果有更多信息可以开始,我可能不会建议它。但我在回答中发布的所有内容都是真实的。
    猜你喜欢
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多