使用php搜索非常大的文件以非常有效地提取块

时间:2012-07-03 21:31:32

标签: php performance file-io

我最近在解析视频文件中的元数据方面遇到了一个令人头痛的问题,发现部分问题是视频制作软件供应商无视各种标准(或至少是互动的差异)(以及其他原因)

因此,我需要能够扫描各种格式,容器和编解码器的非常大的视频(和图像)文件,并挖掘出元数据。我已经有FFMpeg,ExifTool Imagick和Exiv2各自处理各种文件类型的不同类型的元数据,并通过各种其他选项填补其他一些空白(请不要建议库或其他工具,我已经尝试了所有: ))。

现在我要为XMP块扫描大文件(每个高达2GB)(通常由Adobe套件和其他软件写入电影文件)。我已经写了一个功能,但我担心它可以改进。

function extractBlockReverse($file, $searchStart, $searchEnd)
{
    $handle = fopen($file, "r");
    if($handle)
    {
        $startLen = strlen($searchStart);
        $endLen = strlen($searchEnd);

        for($pos = 0, 
                $output = '', 
                $length = 0, 
                $finished = false, 
                $target = '';
            $length < 10000 && 
                !$finished && 
                fseek($handle, $pos, SEEK_END) !== -1; 
            $pos--)
        {
            $currChar = fgetc($handle);
            if(!empty($output))
            {
                $output = $currChar . $output;
                $length++;

                $target = $currChar . substr($target, 0, $startLen - 1);
                $finished = ($target == $searchStart);
            }
            else
            {
                $target = $currChar . substr($target, 0, $endLen - 1);
                if($target == $searchEnd)
                {
                    $output = $target;
                    $length = $length + $endLen;
                    $target = '';
                }
            }
        }

        fclose($handle);
        return $output;
    }
    else
    {
        throw new Exception('not found file');
    }
    return false;
}

echo extractBlockReverse("very_large_video_file.mov", 
    '<x:xmpmeta', 
    '</x:xmpmeta>');

目前它还没问题,但是我真的希望在不破坏我的服务器的情况下充分利用php,所以我想知道是否有更好的方法来做到这一点(或者调整代码会改进它)因为这种方法看起来有点过分,就像找到几个字符串并在它们之间拉出任何东西一样简单。

2 个答案:

答案 0 :(得分:3)

您可以使用其中一种快速字符串搜索算法 - 例如Knuth-Morris-Pratt  或Boyer-Moore以查找开始和结束标记的位置,然后读取它们之间的所有数据。

你应该测量它们的性能,因为如此小的搜索模式可能会导致所选算法的常量不足以使它值得。

答案 1 :(得分:1)

对于文件这么大,我认为最重要的优化是不在任何地方搜索字符串。我不相信视频或图像会在中间有一个XML块 - 或者如果它有,它可能会是垃圾。

好的,有可能 - TIFF可以做到这一点,也可以用JPEG和PNG;为什么不是视频格式呢?但在实际应用中,XMP等松散格式的元数据通常存储在最后。更少见的是,它们存储在文件的开头附近,但这种情况不太常见。

另外,我认为大多数XMP块的尺寸都不会太大(即使Adobe经常填充它们以便能够“几乎总是”快速地就地更新它们。)

所以我的第一次尝试是从文件中提取第一个,例如100 Kb和最后100 Kb的信息。然后扫描这两个块“

如果搜索不成功,您仍然可以执行详尽的搜索,但如果搜索成功,则会在万分之一的时间内返回。相反,即使这个“技巧”仅在一千次中成功一次,它仍然是值得的。