在 PHP 中将大文件写入磁盘的最佳方法是啥?

Posted

技术标签:

【中文标题】在 PHP 中将大文件写入磁盘的最佳方法是啥?【英文标题】:What is the best way to write a large file to disk in PHP?在 PHP 中将大文件写入磁盘的最佳方法是什么? 【发布时间】:2011-06-15 10:38:55 【问题描述】:

我有一个偶尔需要将大文件写入磁盘的 php 脚本。使用file_put_contents(),如果文件足够大(在本例中约为 2 MB),PHP 脚本会耗尽内存(PHP 致命错误:允许的内存大小为 ######## 字节已用尽)。我知道我可以只增加内存限制,但这对我来说似乎不是一个完整的解决方案——必须有更好的方法,对吧?

用 PHP 将大文件写入磁盘的最佳方法是什么?

【问题讨论】:

数据的来源是什么?此外,大多数 PHP 配置应该能够毫无问题地处理 2MB。您的内存限制可能远低于此限制。 文件从何而来?如果它已经存在于磁盘上,那么copy() 将是最合适的。 在这种情况下,我使用 curl 从远程服务器获取文件。所以,我把它放在一个变量中。 跳过 curl,使用copy("http://example.com/file", "/tmp/local.txt") @mario:这很容易,但我正在复制多个文件,我喜欢我可以使用 curl_multi_* 东西同时运行它们 【参考方案1】:

您需要一个临时文件,在其中放置源文件的部分内容以及要附加的内容:

$sp = fopen('source', 'r');
$op = fopen('tempfile', 'w');

while (!feof($sp)) 
   $buffer = fread($sp, 512);  // use a buffer of 512 bytes
   fwrite($op, $buffer);


// append new data
fwrite($op, $new_data);    

// close handles
fclose($op);
fclose($sp);

// make temporary file the new source
rename('tempfile', 'source');

这样,source 的全部内容不会被读入内存。使用 cURL 时,您可以省略设置 CURLOPT_RETURNTRANSFER,而是添加一个写入临时文件的输出缓冲区:

function write_temp($buffer) 
     global $handle;
     fwrite($handle, $buffer);
     return '';   // return EMPTY string, so nothing's internally buffered


$handle = fopen('tempfile', 'w');
ob_start('write_temp');

$curl_handle = curl_init('http://example.com/');
curl_setopt($curl_handle, CURLOPT_BUFFERSIZE, 512);
curl_exec($curl_handle);

ob_end_clean();
fclose($handle);

似乎我总是错过显而易见的事情。正如 Marc 所指出的,有CURLOPT_FILE 可以直接将响应写入磁盘。

【讨论】:

有道理,但在这种情况下,我使用 curl 从不同的服务器检索文件,因此它已经在内存中。 @Joe 我更新了答案。另一个建议来了。 第一个解决方案你可能也用过stream_copy_to_stream ;-) @user576875 不。为什么要轻松? :-) 开玩笑。感谢您的提示。 不需要缓冲。 curl 可以使用curl_setopt('CURLOPT_FILE', ...)直接写入文件【参考方案2】:

使用fwrite()等函数逐行写入(或在二进制文件的情况下逐包写入)

【讨论】:

【参考方案3】:

试试this answer:

    $file   = fopen("file.json", "w");

    $pieces = str_split($content, 1024 * 4);
    foreach ($pieces as $piece) 
        fwrite($file, $piece, strlen($piece));
    

    fclose($file);

【讨论】:

以上是关于在 PHP 中将大文件写入磁盘的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中划分大文件以进行多处理的最佳方法是啥?

在 Perl 中将文件转换为字符串的最佳方法是啥?

在 Java 的并行线程中写入文件的最佳方法是啥?

在 PHP 中将十进制/双精度/浮点值与 PDO 绑定的最佳方法是啥?

将 StringIO 的内容写入文件的最佳方法是啥?

R如何在将csv文件写入磁盘之前估计它的大小