【问题标题】:PHP: How can I grab a single file from a directory without scanning entire directory?PHP:如何在不扫描整个目录的情况下从目录中获取单个文件?
【发布时间】:2012-05-25 10:42:51
【问题描述】:

我有一个包含 130 万个文件的目录,我需要将这些文件移到数据库中。我只需要从目录中获取一个文件名而不扫描整个目录。我抓取哪个文件并不重要,因为我会在完成后将其删除,然后继续下一个。这可能吗?我能找到的所有示例似乎都将整个目录列表扫描到一个数组中。我只需要一次抓取一个来处理...而不是每次 130 万。

【问题讨论】:

  • @JonathanSampson 我怀疑他是否关心文件名。他想抓取任何文件,将其放入数据库,然后移动到下一个。

标签: php file directory


【解决方案1】:

应该这样做:

<?php
$h = opendir('./'); //Open the current directory
while (false !== ($entry = readdir($h))) {
    if($entry != '.' && $entry != '..') { //Skips over . and ..
        echo $entry; //Do whatever you need to do with the file
        break; //Exit the loop so no more files are read
    }
}
?>

readdir

返回目录中下一个条目的名称。这些条目按照文件系统存储它们的顺序返回。

【讨论】:

  • 我宁愿在数据库中插入 '.' 和 '..' 而不是检查 130 万次。
  • @SamyDindane,这项检查不会花很长时间,尤其是与从磁盘读取文件并将其存储在数据库中相比...
  • 不过,只需在循环前对readdir 进行两次调用,就可以避免开销(每一点都有帮助),因为... 始终是第一个条目。
  • @Zombaya 确实,它不需要时间。我在我的电脑上试过:花了 200 毫秒运行 if ($entry != '.' &amp;&amp; $entry != '..') {} 1.3M 次。令人惊讶。
  • 如果目录条目是不需要的,例如另一个目录或符号链接等,则此代码有一个大问题 - better use the standard directory iterator which provides splfileinfo objects
【解决方案2】:

只需获取目录迭代器并查找作为文件的第一个条目:

foreach(new DirectoryIterator('.') as $file)
{
    if ($file->isFile()) {
        echo $file, "\n";
        break;
    }        
}

这还可以确保您的代码在某些其他文件系统行为上执行,而不是您预期的行为。

参见DirectoryIteratorSplFileInfo

【讨论】:

  • 这不是将整个目录内容加载到数组中吗?这就是凯尔试图避免的。当文件夹中有数千个文件时,这可能会有所不同。
  • @skibulk:不,它没有,它遍历 DirectoryIterator,它不是一个数组而是一个对象。这有效地防止了你害怕的东西:一个数组。
  • 酷。我习惯了foreaching 数组。那么当foreach 访问DirectoryIterator 的下一个索引时,它实际上是在调用一个方法(IE getNextFile())呢?奇怪。
  • @skibulk:是的,你可以这样想。更准确地说,它调用DirectoryIterator::next(),这是foreachIterator interface 之间的PHP 合约。更清楚了吗?
【解决方案3】:

readdir 可以解决问题。检查该页面上的示例,但不要在循环中执行 readdir 调用,只需执行一次。您将获得目录中的第一个文件。

注意:您可能会收到“.”、“..”和其他类似的响应,具体取决于服务器,因此您可能希望至少循环直到获得有效文件。

【讨论】:

    【解决方案4】:

    你想返回第一个目录还是第一个文件?两个都?使用这个:

    用 2 个参数创建函数“pickfirst”(地址和模式目录还是文件?)

    function pickfirst($address,$file) { // $file=false >> pick first dir , $file=true >> pick first file
    $h = opendir($address);
    
         while (false !== ($entry = readdir($h))) {
    
              if($entry != '.' && $entry != '..' && ( ($file==false && !is_file($address.$entry)) || ($file==true && is_file($address.$entry)) )  )
              { return $entry; break; } 
    
    } // end while
    } // end function
    

    如果您想选择地址中的第一个目录,请将 $file 设置为 false,如果您希望选择地址中的第一个文件,请将 $file 设置为 true。

    祝你好运:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多