我正在尝试使用QT创建器应用程序创建的C ++程序中的目录递归。出于某种原因,QDir :: entryList和QDirIterator都无法正常工作。使用QDirIterator,我可以找到第二个目录,但是没有更多。当我将QDir :: entryList与嵌套的foreach循环一起使用时,也会发生类似的情况。最终,我希望获得目录链中的最后一个目录,其中不包含其他目录。
这旨在成为跨平台的,因此它不能特定于操作系统。我还希望避免为不同的OS使用大量开关,因为我不想以后再使用它,而只需使用它(可能永远使用)。我尝试过foreach循环,while循环,这是我能想到的。
QDir代码:
QStringList GetLastSubDirs(QDir baseDirectory) {
QStringList result;
baseDirectory.setFilter( QDir::Dirs|QDir::NoDotAndDotDot );
QStringList nonEmptyDirs(baseDirectory.path());
while (nonEmptyDirs.size() > 0) {
foreach (QString d, nonEmptyDirs) {
QDir sd(d);
foreach (QDir checkingDir, sd.entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
if (checkingDir.entryList().size() == 0) {
result.append(checkingDir.path());
} else {
nonEmptyDirs.append(checkingDir.path());
}
}
nonEmptyDirs.removeOne(d);
}
}
if (result.size() == 0) {
result = QStringList(baseDirectory.path());
}
return result;
}
};
这是QDirIterator代码:
class Directories
{
public:
QStringList GetLastSubDirs(QDir baseDirectory) {
QStringList result;
baseDirectory.setFilter( QDir::Dirs|QDir::NoDotAndDotDot );
QDirIterator it(QDir::currentPath() + "/" + baseDirectory.path(), QDirIterator::Subdirectories);
while(it.hasNext()) {
QDir curWorkDir(it.path());
curWorkDir.setFilter( QDir::Dirs|QDir::NoDot|QDir::NoDotDot );
if(curWorkDir.entryList().size() >= 1) {
foreach (QDir d, curWorkDir.entryList()) {
d.setFilter( QDir::Dirs|QDir::NoDot|QDir::NoDotDot );
if (d.entryList().size() <= 0) {
result.append(d.path());
}
}
} else {
result.append(curWorkDir.path());
}
it.next();
}
if (result.size() == 0) {
result = QStringList(baseDirectory.path());
}
return result;
}
};
调试器输出
1 Directories::GetLastSubDirs main.cpp 56 0x555555559ba9
2 Games::Games main.cpp 80 0x555555559f98
3 __static_initialization_and_destruction_0 main.cpp 104 0x55555555931b
4 _GLOBAL__sub_I_main.cpp(void) main.cpp 120 0x55555555934e
5 __libc_csu_init 0x55555555cd9d
6 __libc_start_main libc-start.c 247 0x7ffff54ed270
7 _start 0x555555558f2a
反汇编程序输出:
0x555555558f00 31 ed xor %ebp,%ebp
0x555555558f02 <+ 2> 49 89 d1 mov %rdx,%r9
0x555555558f05 <+ 5> 5e pop %rsi
0x555555558f06 <+ 6> 48 89 e2 mov %rsp,%rdx
0x555555558f09 <+ 9> 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
0x555555558f0d <+ 13> 50 push %rax
0x555555558f0e <+ 14> 54 push %rsp
0x555555558f0f <+ 15> 4c 8d 05 aa 3e 00 00 lea 0x3eaa(%rip),%r8 # 0x55555555cdc0 <__libc_csu_fini>
0x555555558f16 <+ 22> 48 8d 0d 33 3e 00 00 lea 0x3e33(%rip),%rcx # 0x55555555cd50 <__libc_csu_init>
0x555555558f1d <+ 29> 48 8d 3d 74 01 00 00 lea 0x174(%rip),%rdi # 0x555555559098 <main(int, char**)>
0x555555558f24 <+ 36> ff 15 c6 70 20 00 callq *0x2070c6(%rip) # 0x55555575fff0
0x555555558f2a <+ 42> f4 hlt
我希望这个特定的代码片段可以递归目录,直到清除包含其他目录的任何目录为止。相反,它只会下降一个级别并停止。出于某些原因,在查询这些目录的entryList()。size()时,即使目录包含其他目录,它也始终返回0,除非我包含.
和..
,然后它才循环永远,因为它不打算那样处理。
答案 0 :(得分:1)
我不知道你为什么这么复杂。 documentation说:
QDirIterator类为目录条目列表提供了一个迭代器。
您可以使用QDirIterator一次浏览一个目录条目。它与QDir :: entryList()和QDir :: entryInfoList()相似,但是由于它一次列出一个条目,而不是一次列出所有条目,因此扩展性更好,更适合大型目录。它还支持递归列出目录内容以及跟随符号链接。与QDir :: entryList()不同,QDirIterator不支持排序。
QDirIterator构造函数将QDir或目录作为参数。构造之后,迭代器位于第一个目录条目之前。以下是顺序遍历所有条目的方法:
QDirIterator it("/etc", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
// /etc/.
// /etc/..
// /etc/X11
// /etc/X11/fs
// ...
}
在提供QDirIterator :: Subdirectories时,QDirIterator已经是递归的。
答案 1 :(得分:0)
QDir::EntryList
返回子条目的名称,而不是其完整路径。您需要将名称附加到父路径以获取完整路径。
给出层次结构:
basedir/
child1/
child2/
grandchild1/
grandchild2/
在entryList
上调用baseDir
将返回["child1", "child2"]
,而不是["basedir/child1", "basedir/child2"]
正如我在评论中所说:即使您解决了该问题,我也不希望这段代码能正常工作。您正在nonEmptyDirs
的{{1}}循环内修改foreach
。感觉很危险。它肯定不会在C ++ 11的for-for循环中工作。我建议手动写出foreach宏以检查它是否可以工作。特别是,删除当前迭代器指向的列表中的条目并不能很好地结束。
答案 2 :(得分:0)
从Qt documentation ...最重要的最后一句话开始
Qt在进入foreach循环时会自动获取该容器的副本。如果在迭代时修改容器,则不会影响循环。 (如果不修改容器,则仍会进行复制,但是由于隐式共享,复制容器非常快。)
由于foreach创建了容器的副本,因此对变量使用非常量引用将不允许您修改原始容器。它只会影响副本,这可能不是您想要的。