是否存在比file_get_contents更少的内存扩展或更有效的合并MP3方式?

时间:2016-02-21 02:52:06

标签: php memory memory-management file-io

我需要将几个mp3文件合并为一个。

我目前正在这样做:

$combinedFiles = "";
$dir = $_POST['dir'];

if ($handle = opendir($dir)) {
    while (false !== ($entry = readdir($handle))) {
        if ($entry != "." && $entry != "..") {
            $combinedFiles .= file_get_contents(urldecode($dir."/".$entry));
        }
    }

    closedir($handle);
}


file_put_contents("mp3/".$dir.".mp3",   ($combinedFiles));

如果我这样做:

ini_set('memory_limit', -1);

它有效。我已经尝试将此限制设置为4MB,并且它不会引发内存错误,但文件没有创建。没有设置任何限制并保留默认值,我得到分配内存错误。我不想在-1留下它,因为我读过它是不好的做法,可能导致问题。

谢谢(错误不是来自代码中的任何其他地方,我只是运行它。)

编辑:即使设置为8GB,这是我的电脑内存,它也无法正常工作。

3 个答案:

答案 0 :(得分:1)

你可以使用sox,它对我有用了几次

答案 1 :(得分:1)

这种做法怎么样?

<?php
$dir = $_POST['dir'];

if ($handle = opendir($dir))
{
    $outFd = fopen(sprintf("mp3/%s.mp3", $dir), 'wb');

    while (false !== ($entry = readdir($handle)))
    {
        if ($entry != "." && $entry != "..")
        {
            $path = urldecode(sprintf("%s/%s", $dir, $entry));

            $inFd = fopen($path, 'rb');
            stream_copy_to_stream($inFd, $outFd);
            fclose($inFd);
        }
    }

    fclose($outFd);

    closedir($handle);
}

现在,我们遇到了一些安全问题,如果没有正确验证输入,如果这是一个公共工具,您应该修复它们。但是现在我只是讨论手头的问题。

为什么我们不首先打开输出文件,然后将每个输入文件复制到输出文件的末尾,而不是将所有这些文件中的数据一次存储在内存中?我们可以使用stream_copy_to_stream()执行此操作。

我们可以通过stream_set_chunk_size()使用较小的块大小进行操作,但对于您的应用来说,听起来可以暂时将一个MP3存储在内存中(4-5Mb顶部)。您也可以手动一次只读取/写入一个块,而不是使用stream_copy_to_stream(),但总的想法是一样的。

这会导致一次实际存储在内存中的文件少于一个。

答案 2 :(得分:1)

在您的示例中,您将所有文件复制到内存,并在作业完成后将其写回磁盘。

我的建议:

  1. 将第一个文件复制到新位置
  2. 从第二个文件中获取内容并将其附加到复制的文件(file_put_contens FILE_APPEND)
  3. 使用内容
  4. 取消设置变量
  5. 继续第2步,直到完成