以最有效的方式编写一个巨大的文件

时间:2018-05-31 11:38:13

标签: php

我正在尝试在PHP中编写一个50+ MB的文件。

这有点像预期的那样有效,但速度相当慢。

它运行起来非常简单:

$fileAccess = fopen($filename, 'w');
fwrite($fileAccess, $line);
*a lot of lines and loops...*
fclose($fileAccess);

我的问题是。我可以做任何事情来优化它。 我向文件发送大约350000个fwrite大约100-10000个字符的语句,我想知道是否有一些方法可以使文件生成更有效。 做所有这些小写操作是否更好,或者我应该在内部"缓存"在写之前有一些内容,或者是否有我不了解的第三种选择。

我必须降低内存消耗,否则我将达到服务器限制。

由于

3 个答案:

答案 0 :(得分:1)

这可能对您有所帮助

// Copy big file from somewhere else
$src_filepath = 'http://example.com/all_the_things.txt'; $src = fopen($src_filepath, 'r');
$tmp_filepath = '...'; $tmp = fopen($tmp_filepath, 'w');
$buffer_size = 1024;

while (!feof($src)) {                       
   $buffer = fread($src, $buffer_size);     // Read big file/data source/etc. in small chunks
   fwrite($tmp, $buffer);                   // Write in small chunks
}

fclose($tmp_filepath);                      // Clean up
fclose($src_filepath);

rename($tmp_filepath, '/final/path/to/file.txt');

答案 1 :(得分:0)

使用file_put_contents。写入文件是最慢的部分,所以尽可能少地使用它:

$content = '';
$threshold = 1000;
$handler = fopen('my_file.txt', 'a');

foreach ($contents as $i => $data) {
    $content .= $data;

    // Write in batches
    if ($i > $threshold) {
        fwrite($handler, $content);
        $content = ''; // Reset content
    }
}

// Write what's left in $content
if (!empty($content)) {
    fwrite($handler, $content);
}

fclose($handler);

答案 2 :(得分:0)

不是使用许多文件写入的开销,而是只使用一个,例如,我使用一个数组,我最后用新行开头写入;

<?php

$filecontent = array();
$handle = fopen($filename, "w");

while ($x == $y)
{
    if ($condition_met)
    {
        $filecontent[] = "Some message to say this worked";
    }
    if ($condition_met)
    {
        $filecontent[] = "Some message to say this failed";
    }
}

$filecontent = implode("\r\n", $filecontent);
fwrite($handle, $filecontent);
fclose($file);

这意味着您为句柄打开了资源,以及要添加的值数组,只需内插和写入一次通常适用于我

修改

如果你正在使用内存过度使用,仍然使用数组,你可以在最后循环,以避免不断写入写入,但你仍然会看到相同的性能命中,我试图减少这通过添加一个计数器,所以写不是经常做;

$filecontent = array();
$handle = fopen($filename, "w");

while ($x == $y)
{
    if ($condition_met)
    {
        $filecontent[] = "Some message to say this worked";
    }
}
$counts = 0;
$addtofile = "";
foreach ($filecontent as $addline)
{
    if ($counts < 2500)
    {
        $addtofile .= $addline . "\r\n";
        $counts++;
    }
    else
    {
        fwrite($handle, $addtofile);
        $addtofile = "";
        $counts = 0;
    }
}
fclose($file);