【问题标题】:Searching through very large files with php to extract a block very efficiently使用 php 搜索非常大的文件以非常有效地提取块
【发布时间】:2012-07-03 21:31:32
【问题描述】:

我最近一直为从视频文件中解析元数据而头疼,并发现部分问题是视频制作软件供应商无视各种标准(或至少是解释上的差异)(以及其他原因) .

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

现在我要扫描大文件(每个最大 2GB)以查找 XMP 块(通常由 Adob​​e 套件和其他一些软件写入电影文件)。我已经编写了一个函数来做到这一点,但我担心它可以改进。

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 而不会破坏我的服务器,所以我想知道是否有更好的方法来做到这一点(或调整代码改进它)因为这种方法似乎有点过于简单,比如找到几个字符串并在它们之间拉出任何东西。

【问题讨论】:

    标签: php performance file-io


    【解决方案1】:

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

    您应该衡量它们的性能,因为对于如此小的搜索模式,可能会发现所选算法的常数不够好,不值得。

    【讨论】:

      【解决方案2】:

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

      好吧,这是可能的——TIFF 可以做到这一点,JPEG 也可以,PNG 也可以;那么为什么不是视频格式呢?但在现实世界的应用程序中,XMP 等松散格式的元数据通常最后存储。更罕见的是,它们存储在文件开头附近,但这不太常见。

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

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

      如果搜索不成功,您仍然可以运行穷举搜索,但如果成功,它将在千分之一的时间内返回。反之,就算这个“招数”千分之一成功,也还是值得的。

      【讨论】:

      • '通常'XMP 存储在大文件的末尾附近(所以我从最后读取),但即使是同一软件的不同版本似乎也没有保持这一点,所以它们有时可以在奇怪的地方找到(特别是如果头部包含嵌入的预览或其他二进制数据)。我认为接下来的步骤之一是尝试调整代码以添加“考虑区域”以专注于开始和结束,然后仅在必要时搜索中间。谢谢:)
      • 是的,但是即使在缓冲流上搜索“向后”也非常昂贵——大多数实现会在向后搜索时愉快地丢弃缓冲区(确实,仍然存在底层操作系统缓冲,这可以改善这种情况) .最好在结束前直接跳转 100K 或 200K,并向前读取整个块。内存使用量更大,但不是那么多。再说一次,我想这都是尝试的问题——在操作系统、缓冲区、磁盘缓存等之间,有太多因素无法给出一个明确的答案。
      猜你喜欢
      • 2015-03-24
      • 2013-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多