使用SPL的DirectoryTreeIterator为每个目录排序文件 [英] Sorting files per directory using SPL's DirectoryTreeIterator
问题描述
我发现了几个问题(这一个和这个问题)与SPL相关迭代器,但我不确定它们是否对我的情况有帮助,因为我使用的是 RecursiveIteratorIterator
的相当高级别的扩展; DirectoryTreeIterator
。
I found a couple of questions (this one and this question) related to the SPL iterators, but I'm not sure if they're helpful in my case, as I'm using a rather high level extension of the RecursiveIteratorIterator
; the DirectoryTreeIterator
.
有人可能会告诉我如何更改 DirectoryTreeIterator
或者如何在迭代器输出后为每个目录对返回的数组进行排序?
Could somebody perhaps show me how to alter the DirectoryTreeIterator
or how to sort the returned array per directory after it has been outputted by the iterator?
直接在Apache服务器上正确排序文件的方法是如果可以使用 .htaccess
,我也可以选择。
A method of sorting the files correctly directly on the Apache server is also an option for me, if it's possible using .htaccess
for example.
这是<$的代码来自SPL的c $ c> DirectoryTreeIterator :
/** @file directorytreeiterator.inc
* @ingroup Examples
* @brief class DirectoryTreeIterator
* @author Marcus Boerger
* @date 2003 - 2005
*
* SPL - Standard PHP Library
*/
/** @ingroup Examples
* @brief DirectoryIterator to generate ASCII graphic directory trees
* @author Marcus Boerger
* @version 1.1
*/
class DirectoryTreeIterator extends RecursiveIteratorIterator
{
/** Construct from a path.
* @param $path directory to iterate
*/
function __construct($path) {
parent::__construct(
new RecursiveCachingIterator(
new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_FILENAME
),
CachingIterator::CALL_TOSTRING|CachingIterator::CATCH_GET_CHILD
),
parent::SELF_FIRST
);
}
/** @return the current element prefixed with ASCII graphics
*/
function current() {
$tree = '';
for ($l=0; $l < $this->getDepth(); $l++) {
$tree .= $this->getSubIterator($l)->hasNext() ? ' ' : ' ';
}
return $tree . ($this->getSubIterator($l)->hasNext() ? ' ' : ' ')
. $this->getSubIterator($l)->__toString();
}
/** Aggregates the inner iterator
*/
function __call($func, $params) {
return call_user_func_array(array($this->getSubIterator(), $func), $params);;
}
}
澄清为什么我使用上面的代码是因为它完全符合我的需要。我想生成一个以空格为前缀的递归目录树--Marcus Boerger的原始代码示例添加了一些ASCI元素。问题是我无法控制文件和目录的排序,所以我希望目录树看起来像这样:
To clarify why I'm using the code above is because it fits my needs exactly. I want to generate a recursive directory tree prefixed by whitespaces - the original code example by Marcus Boerger adds some ASCI elements. The problem is I don't have control over the sorting of files and directories, so I would like the directory tree to appear like this:
dir001
subdir001
subdir002
subfile001.jpg
file001.png
file002.png
file003.png
dir002
apple.txt
bear.txt
contact.txt
dir003
[...]
相反,迭代器返回的列表根本没有排序,它显示如下:
Instead, the listings returned by the iterator isn't sorted at all and it shows me something like this:
dir002
bear.txt
apple.txt
contact.txt
dir001
subdir001
subdir002
subfile001.jpg
file002.png
file001.png
file003.png
dir003
[...]
所以我想我正在寻找的解决方案是每次将子目录编入索引并添加到目录树时调用排序方法。
So I guess the solution I'm looking for is some way to call a sort method every time a subdirectory is indexed and added to the directory tree.
我希望我能说得更清楚一点非本能的说话者有时候很难把想法变成连贯的句子(甚至是那个问题的单词)。
I hope I've made it somewhat clearer, as a nonnative speaker it's sometimes hard to put thoughts into coherent sentences (or even words for that matter).
推荐答案
嗯,我是不知道你从哪里上课,但它正在做一些相当混乱的事情(包括一些错误至少可以说)。虽然它使用SPL,但它不是SPL类。
Well, I'm not sure where you got that class from, but it's doing some pretty messed up things (including a few bugs to say the least). And while it uses SPL, it's not an SPL class.
现在,我不是100%肯定你的意思是排序,但假设你在谈论一种自然的排序,为什么不只是压平一个阵列,然后对它进行排序?
Now, I'm not 100% sure what you mean by "sort", but assuming you're talking about a natural sort, why not just flatten an array, and then sort it?
$it = new RecursiveTreeIterator(
new RecrusiveDirectoryIterator($dir),
RecursiveTreeIterator::BYPASS_KEY,
CachingIterator::CALL_TOSTRING
);
$files = iterator_to_array($it);
natsort($files);
echo implode("\n", $files);
或
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::SELF_FIRST
);
$files = iterator_to_array($it);
$files = array_map(function($file) { return (string) $file; }, $files);
natsort($files);
echo implode("\n", $files);
编辑:根据您的编辑,以下是我将如何解决此问题:
Based on your edit, here's how I would solve it:
function BuildTree($it, $separator = ' ', $level = '') {
$results = array();
foreach ($it as $file) {
if (in_array($file->getBasename(), array('.', '..'))) {
continue;
}
$tmp = $level . $file->getBaseName();
if ($it->hasChildren()) {
$newLevel = $level . $separator;
$tmp .= "\n" . BuildTree($it->getChildren(), $separator, $newLevel);
}
$results[] = $tmp;
}
natsort($results);
return implode("\n", $results);
};
$it = new RecursiveDirectoryIterator($dir);
$tree = BuildTree($it);
这是一个非常简单的递归解析器,并且在每个级别上进行自然排序。
It's a pretty simple recursive parser, and does the natural sort on each level.
这篇关于使用SPL的DirectoryTreeIterator为每个目录排序文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!