Php 在循环内调用函数会导致超出内存限制

Php 在循环内调用函数会导致超出内存限制,php,arrays,Php,Arrays,我正在用PHP处理一些大文件(300MB-1024MB),以寻找一行符合我的搜索条件并返回整行。由于我无法读取整个文件并将其存储在内存中,因此我逐行阅读: function getLineWithString($fileName, $str) { $matches = array(); $handle = @fopen($fileName, "r"); if ($handle) { while (!feof($handle)) {

我正在用PHP处理一些大文件(300MB-1024MB),以寻找一行符合我的搜索条件并返回整行。由于我无法读取整个文件并将其存储在内存中,因此我逐行阅读:

function getLineWithString($fileName, $str) {

    $matches = array();
    $handle = @fopen($fileName, "r");

    if ($handle) {
        while (!feof($handle)) {
            $buffer = fgets($handle, 4096);

            if (strpos($buffer, $str) !== FALSE) {
                return '<pre>'.$matches[] = $buffer.'</pre>';
            }
        }

        fclose($handle);
    }
}
但是,这种方法(使用
foreach()
)会影响最大执行时间内存限制、Apache的FcgidIOTimeout等。我的数组(指针)包含88个元素,它们的数量可能会根据最终用户的操作而增加,因此这绝对不是一种合适的方法

我的问题是如何防止使用
foreach()
或任何其他循环,并只调用函数一次?

请注意内存泄漏 需要注意的是,这是对“内存泄漏”一词的误用,因为在PHP中,您无法控制内存管理。内存泄漏通常定义为在系统上分配了不再可由该进程访问的内存的进程。在PHP代码中不可能这样做,因为您无法直接控制PHP内存管理器

代码在PHP虚拟机中运行,该虚拟机为您管理内存。超过您在PHP中设置的
内存\u限制
与PHP内存泄漏不是一回事。这是一个定义的限制,由您控制。您可以自行决定提高或降低此限制。例如,您甚至可以通过设置
内存限制=-1
。当然,这仍然取决于您机器的内存容量

你的实际问题 但是,您使用的方法并不比将整个文件读入内存好多少,因为每次搜索(调用函数)时都必须逐行读取文件。这是更糟糕的时间复杂度,尽管它在内存方面可能更有效

为了在时间和内存复杂性方面都高效,您需要在读取文件时立即对每个指针执行搜索。不要将单个针发送到你的函数,而是考虑同时发送整个针阵列。通过这种方式,您可以将用于调用函数的循环延迟到函数本身

此外,您应该注意,在找到匹配项后,当前函数立即返回,因为您正在循环中使用
return
。相反,您应该在函数末尾使用循环外的
return$matches

这里有一个更好的方法

var_dump(getLineWithStrings("somefile.txt", ["foo", "bar", "baz"]));
现在,假设您正在搜索文件中的字符串
“foo”
“bar”
,以及
“baz”
。您可以使用这些字符串的数组对函数进行一次调用,以一次搜索所有字符串,而不是在循环中调用函数。每次从文件中读取一行并搜索
$buffer
中的匹配项时,函数都会循环搜索字符串,然后在完成后返回整个
$matches
数组

请注意 我强烈建议不要使用,因为它会在出现问题时有效地使调试代码变得更加困难,因为它会关闭操作数的所有错误报告。即使出现错误,PHP也不会告诉您,这一点都没有用。

请注意内存泄漏 需要注意的是,这是对“内存泄漏”一词的误用,因为在PHP中,您无法控制内存管理。内存泄漏通常定义为在系统上分配了不再可由该进程访问的内存的进程。在PHP代码中不可能这样做,因为您无法直接控制PHP内存管理器

代码在PHP虚拟机中运行,该虚拟机为您管理内存。超过您在PHP中设置的
内存\u限制
与PHP内存泄漏不是一回事。这是一个定义的限制,由您控制。您可以自行决定提高或降低此限制。例如,您甚至可以通过设置
内存限制=-1
。当然,这仍然取决于您机器的内存容量

你的实际问题 但是,您使用的方法并不比将整个文件读入内存好多少,因为每次搜索(调用函数)时都必须逐行读取文件。这是更糟糕的时间复杂度,尽管它在内存方面可能更有效

为了在时间和内存复杂性方面都高效,您需要在读取文件时立即对每个指针执行搜索。不要将单个针发送到你的函数,而是考虑同时发送整个针阵列。通过这种方式,您可以将用于调用函数的循环延迟到函数本身

此外,您应该注意,在找到匹配项后,当前函数立即返回,因为您正在循环中使用
return
。相反,您应该在函数末尾使用循环外的
return$matches

这里有一个更好的方法

var_dump(getLineWithStrings("somefile.txt", ["foo", "bar", "baz"]));
现在,假设您正在搜索文件中的字符串
“foo”
“bar”
,以及
“baz”
。您可以使用这些字符串的数组对函数进行一次调用,以一次搜索所有字符串,而不是在循环中调用函数。每次从文件中读取一行并搜索
$buffer
中的匹配项时,函数都会循环搜索字符串,然后在完成后返回整个
$matches
数组

请注意
我强烈建议不要使用,因为它会在出现问题时有效地使调试代码变得更加困难,因为它会关闭操作数的所有错误报告。即使出现错误,PHP也不会告诉您,这一点都没有用。

如果是我,我会打电话给grep,并告诉您exec@nogad:我通常倾向于避开涉及另一个la的“混合/部分解决方案”
var_dump(getLineWithStrings("somefile.txt", ["foo", "bar", "baz"]));