QDir类的学习和使用


Qt5的QDir类的学习

文章目录

  • Qt5的QDir类的学习
    • 概述:
      • 相对路径与绝对路径
        • 相对性判断
        • 存在性判断
        • 相对路径转绝对路径
      • 导航和路径操作
        • 获取和设置QDir的值
        • 切换路径
        • 新建删除重命名文件夹
      • 文件和目录内容
        • 过滤文件内容
        • 文件路径添加和删除
      • 当前目录和其他特殊路径
        • 当前目录
        • 特殊路径
      • 路径操作和字符串
      • 附录
        • 文件属性标志
        • 文件排序标志

概述:

? QDir是可以访问 目录结构和目录结构里内容,主要是对目录,但不是对目录里的文件内容的具体信息的操作。为了通俗来学习,我更愿意使用 ‘路径’ 把目录这些词语替换了,QDir是对文件路径的操作的一个类,操作嘛!就像数据库类似!增删改查,更简单就是说,就是两种操作:读写;对 ‘路径’ 这个对象进行一些 读取、写入操作。

1.访问文件路径、2.访问文件路径下的文件信息、3、可以访问底层文件系统、4、访问Qt的资源系统
QDir可以创建、删除、重命名文件夹、删除文件等

Qt全都是使用 “/” (注意区别"\")作为通用目录分隔符,就像在url中使用“/”作为路径分隔符一样。一般我们在Qt上面都是使用的“/”, Windows上面一般都是使用的“\”, 我们其实不用管这些转换问题,Qt将自动转换路径以符合底层操作系统。

相对路径与绝对路径

QDir可以使用相对路径或绝对路径指向文件。绝对路径以目录分隔符(“/”)开头(在Windows下要前面加上盘符)。相对文件名以目录名或文件名开头,并指定相对于当前目录的路径。

1
2
3
4
5
6
7
//使用相对路径
QDir("./zhy/seting");
//使用绝对路径
//windows
QDir("C:/Documents/hello");//因为Windows的路径分隔符是‘\’, 经转换的路径其实是:"C:\Documents\hello",程序拿这个路径去访问文件的
//linux
QDir("/home/user/Documents");//Linux的路径就是"/"所以是直接使用的

相对性判断

我们可以使用以下的函数来确定这个路径的相对性,返回值当然是bool值,看一下这个函数的名字就可以猜出来,后面的const是说这个函数不能去也不要去修改,其保护作用的声明。

bool isAbsolute() const
bool isRelative() const
1
2
3
4
5
6
7
8
QDir one("Users/Administrator");
QDir two("C:/Users/Administrator/Desktop");
qDebug()<<"'/Users/Administrator'  isRelative()? --"<<one.isRelative();
qDebug()<<"'C:/Users/Administrator/Desktop' isAbsolute()? --"<<two.isAbsolute();

//输出如下
'/Users/Administrator'  isRelative()?  --true
'C:/Users/Administrator/Desktop' isAbsolute()?  --true

存在性判断

在不同的操作系统下这个是会判断路径的相对性的,就算你在windows下使用Linux的绝对路径,这个isAbsolute() 返回的值还是false,当然哈,这个函数不会去判断这个路径的真实性,就算你瞎写的只要符合规则,这都会给你返回值,判断你给的路径是否存在是用的另外一个函数

bool exists(const QString &name) const 一般用于给定一个路径 name 来判断,不用再去定义一个对象来判断
bool exists() const 一般是对以初始化(带参构造)QDir对象判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
QDir one("Users/Administrator"); //瞎编的路径、不是当前程序运行的路径
QDir two("C:/Users/Administrator/Desktop");
QDir three;

qDebug()<<"'Users/Administrator' is exist? --"<<one.exists();
qDebug()<<"'C:/Users/Administrator/Desktop' is exits? --"<<two.exists();
qDebug()<<"'D:/keil' is exits? --"<<two.exists("D:/keil");      //
qDebug()<<"'D:/CloudMusic' is exits?"<<three.exists("D:/CloudMusic");

//运行结果
'Users/Administrator' is exist? -- false
'C:/Users/Administrator/Desktop' is exits? -- true
'D:/keil' is exits? -- true
'D:/CloudMusic' is exits? true

相对路径转绝对路径

bool makeAbsolute()
把相对路径转换为绝对路径,成功则返回true否则返回false

导航和路径操作

获取和设置QDir的值

我们可以使用path()函数获取QDir对象的路径,使用setPath()函数给这个QDir对象设置新路径,说白了就是,我们可以通过上面的函数来设置QDir(“xxxx”)里面的xxxx。我们还可以使用absolutePath()获取到这个对象的绝对路径,获取到绝对路径

QString absolutePath() const 返回这个路径,路径不存在就返回当前程序路径,最好不要用’.’ ‘…’
QString path() const 直接返回对象的路径,
void setPath(const QString &path) 设置指定的路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
QDir one("Users/Administrator");
QDir two("C:/Users/Administrator/Desktop");
QDir three("./");

two.setPath("./hello");     //使用setPath("")
qDebug()<<"the one's path --"<<one.path();
qDebug()<<"The Path has changed : --"<<two.path();//获取这个对象的值,
qDebug()<<"the absolutePath: "<<three.absolutePath();

//输出结果
the one's path -- "Users/Administrator"
The Path has changed : -- "./hello"
the absolutePath:  "D:/QTFiles/build-TestNoWidget-Desktop_Qt_5_12_3_MSVC2017_32bit-Debug"
   
/* 为啥需要用这两个函数?
有时候是为了获取一个对象的值,声明的时候是不带参构造的
QDir three;
//...看不见的运算
Filepath = three.path(); //这样就是得到对象的路径值了
*/

使用dirName()函数可以找到目录的名字。这通常返回绝对路径中指定目录位置的最后一个文件夹的名称。但是,如果QDir表示当前目录,它就可以返回“.”

声明 用法例子 结果
QString QDir::dirName() const QDir(“Documents/Letters/Applications”).dirName() // “Applications”
QDir().dirName() // “.”

切换路径

想要切换路径 可以使用 cd() 和 cdUp() 函数更改目录的路径,这两个函数的操作方式与熟悉的shell命令类似。当使用现有目录的名称调用cd()时,QDir对象将更改路径值,其内容也会改变。cdUp() 函数的作用是:更改QDir对象的路径到其父目录;也就是说 cd(“…”)等同于 cdUp()。

bool cd(const QString &dirName) 切换到dirName对应的目录,改变的是这个QDir.path()的值
bool cdUp() 和cd("…")一样,切换到父目录
1
2
3
4
5
6
7
8
9
10
11
12
QDir two("C:/Users/Administrator/Desktop");

qDebug()<<"切换前的路径: "<<two.path();
two.cd("D:/Altium");
qDebug()<<"切换后的路径:"<<two.path();
two.cdUp();
qDebug()<<"切换到父目录"<<two.path();

//运行结果
切换前的路径:  "C:/Users/Administrator/Desktop"
切换后的路径: "D:/Altium"
切换到父目录 "D:/"

新建删除重命名文件夹

现在终于可以 ‘写’目录了,我们可以用mkdir()创建一个子目录,用rename()重命名,用rmdir()删除目录。

返回值就是判断成功与否的,不对的情况说明传入的参数是有误的,也就是说给定的路径有问题

bool mkdir(const QString &dirName) const 根据这个dirName来创建一个子目录,
bool rename(const QString &oldName, const QString &newName) 给老名字一个新名字就是可以了
bool rmdir(const QString &dirName) const 指定要移除的目录
1
2
3
4
5
6
7
8
9
10
11
12
13
//不管这个Dir对象声明没有,都可以做这些操作,都有这些功能,带不带参,都没有影响
QDir one;
QDir two("C:/Users/Administrator/Desktop");
QDir three("./");

qDebug()<<"Rename Hello sucessful?  "<<one.rename("Hello", "World");
qDebug()<<"mak a dir named Hello sucessful?"<<two.mkdir("../Hello");
qDebug()<<"delet the dir named '11' sucessful?"<<three.rmdir("11");

//输出结果
Rename Hello sucessful?   true
mak a dir named Hello sucessful? true
delet the dir named '11' sucessful? true

还可以并且可以使用isReadable()和isRoot()测试目录的属性。

bool isReadable() const 如果目录可读并且可以按名称打开文件,则返回true;否则返回false。
bool isRoot() const 如果目录是根目录,则返回true;否则返回false。Windows就是盘符,Linux就是’/’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
QDir two("C:/Users/Administrator/Desktop");
QDir three("./");

two.cd("D:/Altium");
qDebug()<<"当前是根目录?  "<<two.isRoot();
two.cdUp();
qDebug()<<"当前是根目录? "<<two.isRoot();
qDebug()<<"当前目录可读?"<<two.isReadable();
two.refresh();

//运行结果
当前是根目录?   false
当前是根目录?  true
当前目录可读? true

refresh() 函数的作用是:从磁盘上重新读取目录的数据。这样更安全一点

文件和目录内容

目录下包含许多内容,里面有文件、目录和符号链接(linux的术语,类似Windows下的快捷方式)。count()函数返回目录中的条目数总数。而entryList()函数是获取目录中所有项的名称的字符串列表。如果要得到有关每个条目的信息,请使用entryInfoList()函数得到一个QFileInfo对象的列表。

uint QDir::count() const 返回的是该目录下文件的个数,只是这个对象的子目录,这个同样可以用在entryList().count,
QStringList entryList(QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const 不带参就返回所有的内容,这个带参使用的更好,可以通过设置参数来选择过滤项和排序功能,他有两个重载函数,
QFileInfoList entryInfoList(QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const 返回一个以QFileInfo对象形式存在的列表,根据先前使用setname filters()和setFilter()设置的名称和属性筛选器排序,并根据使用setSorting()设置的标志排序。可以使用name filters、filters和sort参数重写名称筛选器、文件属性筛选器和排序规范。则返回空列表。
1
2
3
4
5
6
7
8
9
10
QDir two("C:/Users/Administrator/Desktop");
two.cd("D:/Altium");
qDebug()<<"the count of two: "<<two.count();
qDebug()<<"目录下的'D:/Altium' 文件列表:"<<two.entryList();
qDebug()<<"目录下的'D:/Altium' 文件列表下的详细信息:"<<two.entryInfoList();

//运行结果
the count of two:  6
目录下的'D:/Altium' 文件列表: (".", "..", "AD18", "Documents", "新建 DOCX 文档.docx", "新建文本文档.txt")
目录下的'D:/Altium' 文件列表下的详细信息: (QFileInfo(D:\Altium\.), QFileInfo(D:\Altium\..), QFileInfo(D:\Altium\AD18), QFileInfo(D:\Altium\Documents), QFileInfo(D:\Altium\新建 DOCX 文档.docx), QFileInfo(D:\Altium\新建文本文档.txt))

过滤文件内容

真正的重点是设置这些参数,那样就可以有选择性的返回我们需要的值

我们可以应用名称过滤器来指定一个模式,该模式包含文件名需要匹配的通配符、一个属性过滤器,该属性过滤器选择条目的属性并可以区分文件、目录、以及排序顺序。

名称过滤器是传递给setNameFilters()的字符串列表。属性过滤器由按位或组合的过滤器组成,这些过滤器在调用setFilter()时指定。排序顺序是使用setSorting()和SortFlags的按位或组合指定的。

可以使用match()函数测试文件名是否与筛选器匹配。调用entryList()和entryInfoList()时,还可以指定筛选器和排序顺序标志,以便覆盖以前定义的行为。

void setNameFilters(const QStringList &nameFilters) 这个nameFilters里面的单个成员是可以使用通配符的,那就非常的灵活的,就像这种 "snn.", ".cpp"等等,这个主要过滤文件的类型
void setFilter(QDir::Filters filters) 这个参数是需要查表来设置的,主要来过滤一下目录下文件的属性,隐藏文件夹啊、可执行文件啊、驱动啊、是普通文件还是目录文件等等,要用 ‘|’运算来设置
void setSorting(QDir::SortFlags sort) 看名字,顾名思义,就是过滤文件排序的属性,也是要查表的,像这些按名称、按时间、按类型、按文件大小等等也是用’|'运算来的
bool match(const QString &filter, const QString &fileName)

这几个函数比较重要我分开记录一下,查看附录可以去查看这些标志的意思

setNameFilters(const QStringList &nameFilters)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//1、一种方法 这是在entryList()里面带参构造的
QDir two;
QStringList filters;
filters<<"*.cpp"<<"*.csv"<<"1.*"<<"2.*";

qDebug()<<"目录下的'D:/Altium' 文件列表:"<<two.entryList(filters);
qDebug()<<"目录下的'D:/Altium' 文件列表下的详细信息:"<<two.entryInfoList(filters);
//-------------------------------------------------------------------------------
//2、二种方法 也可以使用entryList()等函数不带参,用 setNameFilters()来完成
QDir two;
QStringList filters;
filters<<"*.cpp"<<"*.csv"<<"1.*"<<"2.*";
two.setNameFilters(filters);

qDebug()<<"目录下的'D:/Altium' 文件列表:"<<two.entryList();
qDebug()<<"目录下的'D:/Altium' 文件列表下的详细信息:"<<two.entryInfoList();

//运行结果
目录下的'D:/Altium' 文件列表: ("1.xls", "2.dd", "新建文本文档 - 副本.cpp", "新建文本文档 - 副本.csv")
目录下的'D:/Altium' 文件列表下的详细信息: (QFileInfo(D:\Altium\1.xls), QFileInfo(D:\Altium\2.dd), QFileInfo(D:\Altium\新建文本文档 - 副本.cpp), QFileInfo(D:\Altium\新建文本文档 - 副本.csv))

setFilter(QDir::Filters filters) 和 setFilter(QDir::Filters filters),因为entryInfoList和entryList()差不多,我就只用entryList()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//setSorting()函数,
QDir  two;
two.cd("D:/Altium");
two.setSorting(QDir::Name | QDir::Size);
qDebug()<<"目录下的'D:/Altium' 文件列表:"<<two.entryList();

//运行结果
目录下的'D:/Altium' 文件列表: ("1.xls", "2.dd", ".", "..", "AD18", "Documents", "新建 DOCX 文档.docx", "新建文本文档 - 副本.cpp", "新建文本文档 - 副本.csv", "新建文本文档.txt");

//setFilter()函数
QDir  two;
two.cd("D:/Altium");
two.setSorting(QDir::Files);    //过滤去除文件夹,只保留文件
qDebug()<<"目录下的'D:/Altium' 文件列表:"<<two.entryList();

//运行结果--不仅会去掉 ‘.’ 还会去掉 ‘..’
目录下的'D:/Altium' 文件列表: ("1.xls", "2.dd", "新建 DOCX 文档.docx", "新建文本文档 - 副本.cpp", "新建文本文档 - 副本.csv", "新建文本文档.txt")

同样的我们可以在一开始的时候就初始化好entryList()函数,可以参考一下以下的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*这个程序会列出当前文件夹下的所有文件、包括符号链接文件*/
#include <QDir>
#include <iostream>

  int main(int argc, char *argv[])
  {
      QCoreApplication app(argc, argv);
      QDir dir;
      dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
      dir.setSorting(QDir::Size | QDir::Reversed);

      QFileInfoList list = dir.entryInfoList();
      std::cout << "     Bytes Filename" << std::endl;
      for (int i = 0; i < list.size(); ++i) {
          QFileInfo fileInfo = list.at(i);
          std::cout << qPrintable(QString("%1 %2").arg(fileInfo.size(), 10)
                                                  .arg(fileInfo.fileName()));
          std::cout << std::endl;
      }
      return 0;
  }

文件路径添加和删除

我们可以使用filePath()和absoluteFilePath()构造目录下的 文件和目录的路径。啥意思?意思就是说这些个函数啊,它们的返回值是相对于QDir对象路径的指定文件或目录的路径;absoluteFilePath()返回指定文件或目录的绝对路径。这些函数都不检查文件或目录的存在;它们只负责构造这样一个文件路径。这点要注意哈!

QString filePath(const QString &fileName) const 其实只是返回的一个新的路径,有点类似字符串里的重载运算符 + ,拼接俩字符串形成一个新的字符串返回
QString absoluteFilePath(const QString &fileName) const 和filePath()类似,只是返回的是绝对路径,上面的可以是相对路径或绝对路径
bool remove(const QString&fileName) 这个和这个可以形成对比,这个是从目录中删除文件,是真的删除,可以联系到上面的删除目录是使用的 rmdir("");函数
1
2
3
4
5
6
7
8
9
10
11
QDir two("C:/Users/Administrator/Desktop");

two.cd("D:/Altium");
qDebug()<<"'D:/Altium' 下的文件构造路径"<<two.filePath("helloworld");
qDebug()<<"'D:/Altium' 下的文件构造路径"<<two.absoluteFilePath("1313/sfdf");
qDebug()<<"删除 '新建文本文档.txt' 成功?  "<<two.remove("新建文本文档.txt");

//运行结果
'D:/Altium' 下的文件构造路径 "D:/Altium/helloworld"
'D:/Altium' 下的文件构造路径 "D:/Altium/1313/sfdf"
删除 '新建文本文档.txt' 成功?   true

当前目录和其他特殊路径

当前目录

对一些常见目录的访问提供了许多静态函数,下面这些函数返回QDir对象。这些函数也有相应的函数返回字符串:

返回值是:QDir 返回值是:QString QDir的一个部分是QString
current() currentPath() 返回当前的目录路径
home() homePath() 返回当前用户的所在目录
root() rootPath() linux返回‘/’,windows则是返回“C:/”
temp() tempPath() 返回用户的临时目录

关于这个两个的关系:QDir构造的对象是已经初始化的对象,后面是任何QDir对象都可以使用的,而且获取的值都是一样的

1
2
3
4
QDir one;

QDir::current().currentPath() 的值是等于  one.currentPath()
QDir::current() 不等于  one

特殊路径

setCurrent() 静态函数是常用于设置软件程序的工作路径的,如果你想找到这个可执行程序的路径,你可以使用这个函数 QCoreApplication::applicationDirPath(),drives()静态函数为包含文件系统的每个设备提供根目录列表。在Unix系统上,这将返回一个包含单个根目录“/”的列表;在Windows系统上,该列表通常包含C:/,可能还包含其他驱动器号,如D:/,具体取决于用户系统的配置。

bool setCurrent(const QString &path) 将应用程序的当前工作目录设置为路径。如果成功更改目录,则返回true;否则返回false
QString QCoreApplication::applicationDirPath() 注意是返回的当前运行程序的目录路径,不是Qt的安装路径,也不是这可执行文件的具体路径
QFileInfoList drives() 其实就是返回这个磁盘驱动器的,Windows返回所有的盘符,像“C: / ”,“D: /”,等等,但是在Linux是一个唯一的根目录“ / ”
1
2
3
4
5
6
7
8
9
10
11
12
QDir one;

qDebug()<<"设置路径:"<<one.setCurrent("D:/");
qDebug()<<"设置完成的路径:"<<one.path();
qDebug()<<"当前可执行文件的路径:"<<QCoreApplication::applicationDirPath();
qDebug()<<"当前系统的驱动器:"<<one.drives();

//运行结果
设置路径: true
设置完成的路径: "."
当前可执行文件的路径: "D:/QTFiles/build-TestNoWidget-Desktop_Qt_5_12_3_MSVC2017_32bit-Debug/debug"
当前系统的驱动器: (QFileInfo(C:\), QFileInfo(D:\))

路径操作和字符串

这部分我也不太明白

使用canonical path()函数,可以将包含“.”元素(在路径中的该点引用当前目录)、“…”元素(引用父目录)和符号链接的路径缩减为规范形式。
还可以通过使用cleanPath()删除多余的“/”和“…”元素来简化路径。有时需要能够在用户平台的本机表示中显示路径。函数的作用是:返回一个指定路径的副本,在该路径中,每个目录分隔符都将替换为基础操作系统的相应分隔符。

cleanPath()返回标准化目录分隔符(转换为“/”)并删除多余分隔符的路径,并尽可能解析“.s”和“…s”。保留符号链接。此函数不返回规范路径,而是返回输入的最简单版本。例如,“./local”变为“local”,“local/./bin”变为“bin”和“/local/usr/./bin”变为“/local/bin”

附录

文件属性标志

QDir::Dirs 0x001 List directories that match the filters.
QDir::AllDirs 0x400 List all directories; i.e. don’t apply the filters to directory names.
QDir::Files 0x002 List files.
QDir::Drives 0x004 List disk drives (ignored under Unix).
QDir::NoSymLinks 0x008 Do not list symbolic links (ignored by operating systems that don’t support symbolic links).
QDir::NoDotAndDotDot NoDot | NoDotDot Do not list the special entries “.” and “…”.
QDir::NoDot 0x2000 Do not list the special entry “.”.
QDir::NoDotDot 0x4000 Do not list the special entry “…”.
QDir::AllEntries Dirs | Files | Drives List directories, files, drives and symlinks (this does not list broken symlinks unless you specify System).
QDir::Readable 0x010 List files for which the application has read access. The Readable value needs to be combined with Dirs or Files.
QDir::Writable 0x020 List files for which the application has write access. The Writable value needs to be combined with Dirs or Files.
QDir::Executable 0x040 List files for which the application has execute access. The Executable value needs to be combined with Dirs or Files.
QDir::Modified 0x080 Only list files that have been modified (ignored on Unix).
QDir::Hidden 0x100 List hidden files (on Unix, files starting with a “.”).
QDir::System 0x200 List system files (on Unix, FIFOs, sockets and device files are included; on Windows, .lnk files are included)
QDir::CaseSensitive 0x800 The filter should be case sensitive.

文件排序标志

QDir::Name 0x00 Sort by name.
QDir::Time 0x01 Sort by time (modification time).
QDir::Size 0x02 Sort by file size.
QDir::Type 0x80 Sort by file type (extension).
QDir::Unsorted 0x03 Do not sort.
QDir::NoSort -1 Not sorted by default.
QDir::DirsFirst 0x04 Put the directories first, then the files.
QDir::DirsLast 0x20 Put the files first, then the directories.
QDir::Reversed 0x08 Reverse the sort order.
QDir::IgnoreCase 0x10 Sort case-insensitively
QDir::LocaleAware 0x40 Sort items appropriately using the current locale settings.