【问题标题】:Select random file using OPENDIR()使用 OPENDIR() 选择随机文件
【发布时间】:2012-08-25 05:02:43
【问题描述】:

我试过了:

function random_pic($dir = '../myfolder') {
    $files = opendir($dir . '/*.*');
    $file = array_rand($files);
    return $files[$file];
}

这个函数使用glob()而不是opendir。

这会返回打开目录失败的错误。我猜opendir不能接受*.*之类的东西?是否可以选择文件夹中的所有文件并随机选择一个?

【问题讨论】:

  • 还有...使用glob() 有什么问题?另外,为了使用...dir()函数,你需要在这种情况下使用scandir()函数。
  • 好吗?除非你把它用于错误的事情......
  • opendir 在您的代码中毫无意义。根据相关的手动输入,它返回一个资源。你打电话给array_rand。显然,这是行不通的,因为资源不是数组。我以某种方式怀疑您在同一任务上“基准化”了opendirglob 之间的差异,因为这就像将苹果与天花进行比较。它们不一样。
  • 赞成苹果与天花的比较。 opendir 可能不会更快,但它可能会稍微提高内存效率,因为您不必生成整个数组。

标签: php opendir


【解决方案1】:

opendir() 函数不会返回文件/文件夹列表。它只会打开一个可供closedir()readdir()rewinddir() 使用的句柄。这里的正确用法是glob(),但我看到您不希望这样,您也可以使用scandir(),如下所示:

<?php
$path = "./";

$files = scandir($path);
shuffle($files);

for($i = 0; ($i < count($files)) && (!is_file($files[$i])); $i++);

echo $files[$i];
?>

在你承认我没有“错”之后,我很乐意看看这是否需要更长时间,或者glob() 是否需要更长时间。

【讨论】:

  • 很高兴您寻求我承认我认为您是对还是错,基准测试结果表明您是错误的。感谢您的意见。
  • 你是什么意思基准测试结果显示我错了......这没有任何意义。你不能在这里使用opendir()。您的选项是scandir()glob()。在我继续继续之前,这就是我们正在争论的问题(据我所知)。你认为opendir() 在这里有用吗?另一种选择是readdir(),它将使用opendir() 创建的句柄,但opendir() 仍然不返回文件数组...
  • 我的第一语言是英语(如果不是...,那真的没关系)。我的问题是你所说的与我试图向你解释的无关。你也忽略了我的问题,你能解释一下吗?
  • @Norse:你猜怎么着?更快地搞砸仍然只是搞砸。 性能比较意味着没有任何意义,除非两个程序都能正常工作。而且由于你的显然没有,任何比较都是没有意义的。做错事需要多长时间都没关系。
  • 我投了反对票,因为我觉得这没有回答这个问题,当我有同样的问题时它也没有帮助我。我真的不在乎你和op吵架,我只是想要最好的答案。今天在这些方法上花了几个小时后,我修改了我的答案以尝试显示更多结果,只是为了测试最有效的方法。最后,我喜欢opendir 并且如前所述,与scandir 几乎没有区别。周末愉快。
【解决方案2】:

以下2种方法利用opendir快速读取目录并返回随机文件或目录。


  • 完成的所有基准测试均使用 CI3 并且是 100 个脉冲的平均值。
    在 Win10 Intel i54460 w/16GB RAM 上使用 WAMP

获取随机文件:

function getRandomFile($path, $type=NULL, $contents=TRUE) {
    if (strpos($path, $_SERVER['DOCUMENT_ROOT']) === FALSE) $path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path;
    if (is_dir($path)) {
        if ($dh = opendir($path)) {
            $arr = [];
            while (false !== ($file = readdir($dh))) {
                //  not a directory
                if (!is_dir("$path/$file") && !preg_match('/^\.{1,2}$/', $file)) {
                    //  fits file type
                    if(is_null($type)) $arr[] = $file;
                    elseif (is_string($type) && preg_match("/\.($type)$/", $file)) $arr[] = $file;
                    elseif (is_array($type)) {
                        $type = implode('|', $type);
                        if (preg_match("/\.($type)$/", $file)) $arr[] = $file;
                    }
                }
            }
            closedir($dh);
            if (!empty($arr)) {
                shuffle($arr);
                $file = $arr[mt_rand(0, count($arr)-1)];
                return empty($contents) ? $file : ($contents == 'path' ? "$path/$file" : file_get_contents($file));
            }
        }
    }
    return NULL;
}

使用简单:
//  Benchmark 0.0018 seconds *
$this->getRandomFile('directoryName');
//  would pull random contents of file from given directory

//  Benchmark 0.0017 seconds *
$this->getRandomFile('directoryName', 'php');
//  |OR|
$this->getRandomFile('directoryName', ['php', 'htm']);
//  one gets a random php file 
//  OR gets random php OR htm file contents

//  Benchmark 0.0018 seconds *
$this->getRandomFile('directoryName', NULL, FALSE);
//  returns random file name

//  Benchmark 0.0019 seconds *
$this->getRandomFile('directoryName', NULL, 'path');
//  returns random full file path

获取随机目录:

function getRandomDir($path, $full=TRUE, $indexOf=NULL) {
    if (strpos($path, $_SERVER['DOCUMENT_ROOT']) === FALSE) $path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path;
    if (is_dir($path)) {
        if ($dh = opendir($path)) {
            $arr = [];
            while (false !== ($dir = readdir($dh))) {
                if (is_dir("$path/$dir") && !preg_match('/^\.{1,2}$/', $dir)) {
                    if(is_null($indexOf)) $arr[] = $file;
                    if (is_string($indexOf) && strpos($dir, $indexOf) !== FALSE) $arr[] = $dir;
                    elseif (is_array($indexOf)) {
                        $indexOf = implode('|', $indexOf);
                        if (preg_match("/$indexOf/", $dir)) $arr[] = $dir;
                    }
                }
            }
            closedir($dh);
            if (!empty($arr)) {
                shuffle($arr);
                $dir = $arr[mt_rand(0, count($arr)-1)];
                return $full ? "$path/$dir" : $dir;
            }
        }
    }
    return NULL;
}

使用简单:
//  Benchmark 0.0013 seconds *
$this->getRandomDir('parentDirectoryName');
//  returns random full directory path of dirs found in given directory

//  Benchmark 0.0015 seconds *
$this->getRandomDir('parentDirectoryName', FALSE);
//  returns random directory name

//  Benchmark 0.0015 seconds *
$this->getRandomDir('parentDirectoryName', FALSE, 'dirNameContains');
//  returns random directory name

在组合中使用类似:

$dir = $this->getRandomDir('dirName');
$file = $this->getRandomFile($dir, 'mp3', FALSE);
//  returns a random mp3 file name. 
//  Could be used to load random song via ajax.

single line

/** getRandomFile(String)
 *  Simple method for retrieving a random file from a directory
 **/
function getRandomFile($path, $type=NULL, $contents=TRUE) { if (strpos($path, $_SERVER['DOCUMENT_ROOT']) === FALSE) $path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path; if (is_dir($path)) { if ($dh = opendir($path)) { $arr = []; while (false !== ($file = readdir($dh))) { if (!is_dir("$path/$file") && !preg_match('/^\.{1,2}$/', $file)) { if(is_null($type)) $arr[] = $file; elseif (is_string($type) && preg_match("/\.($type)$/", $file)) $arr[] = $file; elseif (is_array($type)) { $type = implode('|', $type); if (preg_match("/\.($type)$/", $file)) $arr[] = $file; } } } closedir($dh); if (!empty($arr)) { shuffle($arr); $file = $arr[mt_rand(0, count($arr)-1)]; return empty($contents) ? $file : ($contents == 'path' ? "$path/$file" : file_get_contents($file)); } } } return NULL; }

/** getRandomDir(String)
 *  Simple method for retrieving a random directory
 **/
function getRandomDir($path, $full=TRUE, $indexOf=NULL) { if (strpos($path, $_SERVER['DOCUMENT_ROOT']) === FALSE) $path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path; if (is_dir($path)) { if ($dh = opendir($path)) { $arr = []; while (false !== ($dir = readdir($dh))) { if (is_dir("$path/$dir") && !preg_match('/^\.{1,2}$/', $dir)) { if(is_null($indexOf)) $arr[] = $file; if (is_string($indexOf) && strpos($dir, $indexOf) !== FALSE) $arr[] = $dir; elseif (is_array($indexOf)) { $indexOf = implode('|', $indexOf); if (preg_match("/$indexOf/", $dir)) $arr[] = $dir; } } } closedir($dh); if (!empty($arr)) { shuffle($arr); $dir = $arr[mt_rand(0, count($arr)-1)]; return $full ? "$path/$dir" : $dir; } } } return NULL; }

/*  This is only here to make copying easier.   */

只是关于glob && scandir 的注释。
我使用每一个都制作了getRandomDir 的替代版本。
使用scandir 在基准测试中几乎没有差异(从-.001 到+.003)
使用glob 的速度明显变慢!每次通话的差异从 +.5 到 +1.100 不等。

【讨论】:

  • .. 假设你 dv'd 我?为什么?这个答案也具有欺骗性,因为 opendir 并不是真正选择随机文件的函数
  • @Jeremy 没有什么欺骗性的。它按照OP的要求和我想要做的那样做。它确实使用 opendir,正如 opendir 所期望的那样。你的回答根本没有。 opendir 旨在打开一个目录进行读取,然后使用 readdir 获取所需的信息,然后关闭并继续。这真的很简单,基准测试也很好。抱歉,您的旧答案没有对这个问题得出正确的结论,在寻求这个答案时肯定对我没有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
  • 2017-01-25
  • 2011-02-20
  • 2012-03-03
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多