QDir类提供了访问目录结构和目录内容的功能。它一般被用来操作路径名,访问路径和文件的信息。还可以用来访问Qt的资源系统。Qt使用"/"作为统一的目录分隔符,类似于在URL中所使用的那样。
一个QDir对象可以通过相对路径或绝对路径指向一个文件。其中,绝对路径以目录分隔符开始(在Windows平台就是磁盘标识符);相对路径开始于一个目录名或一个文件名,相对于当前目录。如下面代码所示,使用绝对路径创建了QDir对象:
QDir("/home/user/Documents")
QDir("C:/Documents and Settings")
在Windows平台上,上面第二个例子会被转换为C:\Documents and Settings。
使用相对路径的例子如下:
QDir("images/landscape.png")
一个目录的路径可以通过path() 函数获得,其返回一个初始化该对象时所使用的字符串,也可以通过setPath() 来为一个QDir对象重新赋值。absolutePath() 可以获得当前QDir对象的绝对路径表示。一个目录的最后一部分称为该目录的名字,可以使用dirName() 函数获取该名字。如下代码所示:
QDir("Documents/Letters/Applications").dirName() // "Applications"
QDir().dirName() // "."
通常,一个目录里会包含很多条目,其中包括文件,目录和符号链接。我们可以使用count() 函数得到一个目录下包含的条目数。还可以使用entryList() 和 entryInfoList() 函数获得这些条目所组成的链表,然后逐个分析。还可以在调用这两个函数时指定一个过滤器,按一定模式筛选要返回的条目;也可以再提供一个排序规则,按一定顺序返回需要的条目。
在QDir中,还为我们提供了访问特定目录的方法,如下表,此处根据不同的返回值进行了分类:
QDir | QString | Reture Value |
current() | currentPath() | 应用程序的工作目录 |
home() | homePath() | 用户的家目录 |
root() | rootPath() | 系统的根目录 |
temp() | tempPath() | 系统的临时目录 |
静态方法setCurrent() 也可以用来设置应用程序的工作目录。其实,QCoreApplication也提供了applicationDirPath() 方法,以返回应用程序的工作目录。
另一个比较有用的静态方法是drives(),返回当前系统上的所有文件系统的根目录列表。在Unix平台上,该列表值包含一个"/";在Windows平台上,该列表包含当前系统上所有的盘符。
除此之外,我们还可以使用cannonicalPath() 获得一个链接的实际路径;使用cleanPath() 去除路径中多余的"/" 和 "..";使用toNativeSeparators() 返回一个包含特定平台的目录分隔符的路径。
下面,我们写一个遍历某个目录下的全部文件的例子,来简单使用一写该类的常用函数:
思路是,先用要遍历的目录创建一个QDir对象,然后调用entryInfoList() 返回该目录下的所以条目的QFileInfoList,在遍历该list,对里面的每一QFileInfo 进行处理,根据其是否是子目录,来决定进一步的变量工作。代码如下:
#include
#include
#include
#include
void TraceDir(QString path)
{
QDir dir(path);
if(!dir.exists() || !dir.makeAbsolute())
{
return ;
}
QFileInfoList list = dir.entryInfoList();
for(QFileInfo info : list)
{
if(info.fileName() == "." || info.fileName() == "..")
{
//排除 .和..
continue;
}
if(info.isDir())
{
//如果是目录,则进行递归遍历
TraceDir(info.filePath());
}
else
{
//普通文件,则直接输出
qDebug() << info.filePath();
}
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//变量Qt的根目录
TraceDir("D:/Qt/Qt5.7.0/");
return a.exec();
}
在此,我们使用递归的方式,遍历了Qt的主目录。
部分输出结果截图如下:
因为我安装了Qt的源码,所以遍历的过程相当的慢。其实,如果我们只需要某几种类型的文件的话,我们可以在创建QDir对象或调用entryInfoList() 时指定一个过滤器,比如过滤特定名字的文件,特定后缀的文件等等。
上面,我们在遇到子目录时,采用了递归的方式来遍历。其实,谈到遍历目录,Qt中专门为我们提供了一个迭代器类QDirIterator。这个类的功能类似于entryList() 或者 enteryInfoList(),但是,它一次只遍历一个条目,而entryList()是一下返回目录中所有的条目,所以QDirIterator的弹性更好,更适用于大目录的遍历。同时,它天然可以对目录自动进行递归遍历,并且能够跟踪符号链接。但它不支持entryList() 的排序功能。其构造函数如下:
QDirIterator(const QDir &dir, IteratorFlags flags = NoIteratorFlags)
QDirIterator(const QString &path, IteratorFlags flags = NoIteratorFlags)
QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags = NoIteratorFlags)
QDirIterator(const QString &path, const QStringList &nameFilters, QDir::Filters filters = QDir::NoFilter, IteratorFlags flags = NoIteratorFlags)
QDirIterator it("/etc", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
// /etc/.
// /etc/..
// /etc/X11
// /etc/X11/fs
// ...
}
这种方式其实类似于Java中的迭代器使用方式。next() 函数会返回下一个条目并将迭代器前进一步。但是,QDirIterator是单向的,即你不能反向遍历,也不能进行随机遍历。
下面,我们使用这个来重写我们上面的目录遍历函数:
使用这个类来完成的话,我们就不需要使用递归的方式了。因为,上面已经说了,QDirIterator天然就可以自动遍历子目录,只需要在构造函数中传入一个QDirIterator::Subdirectories即可。代码如下:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//变量Qt的根目录
//TraceDir("D:/Qt/Qt5.7.0/");
QDir dir("D:/Qt/Qt5.7.0/");
QDirIterator iter(dir, QDirIterator::Subdirectories);
while(iter.hasNext())
{
qDebug() << iter.next();
}
return a.exec();
}