读取文件内容的最快方式

2022-08-30 14:29:31

好的,我正在寻找最快的方法,通过php读取文件的所有内容,并在服务器上使用文件路径,这些文件也可能很大。因此,尽快对它执行只读非常重要。

逐行阅读是否比阅读整个内容更快?不过,我记得读过一些,阅读整个内容可能会对大文件产生错误。这是真的吗?


答案 1

如果要将文件的完整内容加载到PHP变量中,最简单(也可能是最快)的方法就是file_get_contents

但是,如果您正在处理大文件,则将整个文件加载到内存中可能不是一个好主意:您可能最终会遇到memory_limit错误,因为PHP不允许脚本使用超过(通常)几兆字节的内存。


因此,即使它不是最快的解决方案,也可能需要逐行读取文件fopen + fgets + fclose),并动态使用这些行,而无需将整个文件加载到内存中...


答案 2

file_get_contents()是PHP中读取文件的最优化方式,但是 - 由于您正在读取内存中的文件,因此始终限制为可用的内存量

如果您具有正确的权限,则可以发出a,但您仍然会受到系统上可用内存量的限制,这适用于所有编程语言。ini_set('memory_limit', -1)

唯一的解决方案是以块的形式读取文件,因为您可以将其与第四个和第五个参数(和 - 以字节为单位指定)一起使用file_get_contents()$offset$maxlen

string file_get_contents(string $filename[, bool $use_include_path = false[, resource $context[, int $offset = -1[, int $maxlen = -1]]]])

下面是一个示例,其中我使用此技术来提供大型下载文件:

public function Download($path, $speed = null)
{
    if (is_file($path) === true)
    {
        set_time_limit(0);

        while (ob_get_level() > 0)
        {
            ob_end_clean();
        }

        $size = sprintf('%u', filesize($path));
        $speed = (is_int($speed) === true) ? $size : intval($speed) * 1024;

        header('Expires: 0');
        header('Pragma: public');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-Type: application/octet-stream');
        header('Content-Length: ' . $size);
        header('Content-Disposition: attachment; filename="' . basename($path) . '"');
        header('Content-Transfer-Encoding: binary');

        for ($i = 0; $i <= $size; $i = $i + $speed)
        {
            ph()->HTTP->Flush(file_get_contents($path, false, null, $i, $speed));
            ph()->HTTP->Sleep(1);
        }

        exit();
    }

    return false;
}

另一种选择是使用优化较少的,和函数,特别是如果您关心一次获取整行,这是我在另一个StackOverflow问题中提供的另一个示例,用于将大型SQL查询导入数据库fopen()feof()fgets()fclose()

function SplitSQL($file, $delimiter = ';')
{
    set_time_limit(0);

    if (is_file($file) === true)
    {
        $file = fopen($file, 'r');

        if (is_resource($file) === true)
        {
            $query = array();

            while (feof($file) === false)
            {
                $query[] = fgets($file);

                if (preg_match('~' . preg_quote($delimiter, '~') . '\s*$~iS', end($query)) === 1)
                {
                    $query = trim(implode('', $query));

                    if (mysql_query($query) === false)
                    {
                        echo '<h3>ERROR: ' . $query . '</h3>' . "\n";
                    }

                    else
                    {
                        echo '<h3>SUCCESS: ' . $query . '</h3>' . "\n";
                    }

                    while (ob_get_level() > 0)
                    {
                        ob_end_flush();
                    }

                    flush();
                }

                if (is_string($query) === true)
                {
                    $query = array();
                }
            }

            return fclose($file);
        }
    }

    return false;
}

您使用哪种技术实际上取决于您尝试执行的操作(正如您在SQL导入功能和下载功能中看到的那样),但您始终必须以块的形式读取数据


推荐