Qt5 C++14教程--Qt5文件和目录

本文介绍了Qt5中处理文件和目录的方法,包括使用QFile、QDir和QFileInfo类进行文件大小查询、读取、写入、复制、权限检查以及目录管理等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Qt5 C++编程教程的这一部分,我们要处理文件和目录。

QFile、QDir和QFileInfo是Qt5中处理文件的基本类。QFile 提供了一个读取和写入文件的接口。QDir 提供了对目录结构和其内容的访问。QFileInfo 提供与系统无关的文件信息,包括文件的名称和在文件系统中的位置、访问时间和修改时间、权限或文件所有权。

Qt5 文件大小

下面是一个求文件大小的例子。

file_size.cpp
#include <QTextStream>
#include <QFileInfo>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 2) {

    qWarning("Usage: file_size file");
    return 1;
  }

  QString filename = argv[1];

  QFile f{filename};

  if (!f.exists()) {

    qWarning("The file does not exist");
    return 1;
  }

  QFileInfo fileinfo{filename};

  qint64 size = fileinfo.size();

  QString str = "The size is: %1 bytes";

  out << str.arg(size) << endl;

  return 0;
}

QString filename = argv[1];

文件名作为程序的参数传递。

QFile f{filename};

if (!f.exists()) {

qWarning("The file does not exist");

return 1;

}

使用 QFile 类的 exists 方法检查文件是否存在。如果不存在,我们发出警告并终止程序。

QFileInfo fileinfo{filename};

创建 QFileInfo 的实例。

qint64 size = fileinfo.size();

使用 size 方法确定文件的大小。qint64 是一种在 Qt 支持的所有平台上都保证为 64 位的类型。

QString str = "The size is: %1 bytes";

out << str.arg(size) << endl;

结果输出到控制台。

$ ./filesize Makefile

The size is: 19993 bytes

Qt5读取文件

为了读取文件的内容,我们必须首先以只读模式打开文件。然后创建输入文件流;从该流中读取数据。

words.txt

sky

blue

cloud

falcon

forest

lake

cup

bear

wolf

我们有一个样本文本文件。

read_file.cpp
#include <QTextStream>
#include <QFile>

int main(void) {

  QTextStream out{stdout};

  QFile f{"words.txt"};

  if (!f.open(QIODevice::ReadOnly)) {

    qWarning("Cannot open file for reading");
    return 1;
  }

  QTextStream in{&f};

  while (!in.atEnd()) {

    QString line = in.readLine();
    out << line << endl;
  }

  return 0;
}

该例子从word.txt文件中读取数据。

QFile f{"words.txt"};

创建一个QFile对象的实例。 QFile在范围外时自动关闭文件。

if (!f.open(QIODevice::ReadOnly)) {

qWarning("Cannot open file for reading");

return 1;

}

QFile的open方法以只读模式打开文件。如果该方法失败,我们发出警告并终止程序。

QTextStream in{&f};

创建输入流。 QTextStream接收文件句柄。数据将从此流中读取。

while (!in.atEnd()) {

QString line = in.readLine();

out << line << endl;

}

在while循环中,我们逐行读取文件,直到文件结束。 atEnd方法如果没有更多数据从流读取,则返回true。readLine方法从流读取一行。

$ ./readfile

sky

blue

cloud

falcon

forest

lake

cup

bear

wolf

Qt5写文件

为了写入文件,我们在写入模式下打开文件,创建一个向文件输出的输出流,并使用写操作符写入该流。

write_file.cpp
#include <QTextStream>
#include <QFile>

int main(void) {

  QTextStream out{stdout};

  QString filename = "distros.txt";
  QFile f{filename};

  if (f.open(QIODevice::WriteOnly)) {

    QTextStream out{&f};
    out << "Xubuntu" << endl;
    out << "Arch" << endl;
    out << "Debian" << endl;
    out << "Redhat" << endl;
    out << "Slackware" << endl;

  } else {

    qWarning("Could not open file");
  }

  return 0;
}

这个例子将五个Linux发行版的名称写入名为distrost.txt的文件中。

QString filename = "distros.txt";

QFile f{filename};

使用提供的文件名创建QFile对象。

if (f.open(QIODevice::WriteOnly)) {

使用open方法,我们以只写方式打开文件。

QTextStream out{&f};

这一行创建了一个操作文件句柄的QTextStream。换句话说,要写入的数据流被导向到文件。

out << "Xubuntu" << endl;

out << "Arch" << endl;

out << "Debian" << endl;

out << "Redhat" << endl;

out << "Slackware" << endl;

使用<<运算符写入数据。

$ ./writefile

$ cat distros.txt

Xubuntu

Arch

Debian

Redhat

Slackware

复制文件

当我们复制文件时,我们创建一个文件的精确复制,具有不同的名称或在文件系统的不同位置。

copy_file.cpp
#include <QTextStream>
#include <QFile>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 3) {

      qWarning("Usage: copyfile source destination");
      return 1;
  }

  QString src = argv[1];

  if (!QFile{src}.exists()) {

      qWarning("The source file does not exist");
      return 1;
  }

  QString dest(argv[2]);

  QFile::copy(src, dest);

  return 0;
}

这个例子使用QFile :: copy方法创建提供文件的副本。

if (argc != 3) {

kotlinCopy codeqWarning("Usage: copyfile source destination");

return1;

}

该程序需要两个参数;如果没有给出,则以警告消息结束。

QString src = argv[1];

从程序的命令行参数中获取源文件的名称。

if (!QFile{src}.exists()) {

qWarning("The source file does not exist");

return 1;

}

我们使用QFile的exists方法检查源文件的存在性。如果不存在,则以警告消息结束程序。

QString dest(argv[2]);

我们获取目标文件名。

QFile::copy(src, dest);

使用QFile :: copy方法复制源文件。

第一个参数是源文件名,第二个参数是目标文件名。

每个文件都有一个拥有者。为了更好地管理和保护文件,文件还属于一组用户。

主程序:

owner_group.cpp
#include <QTextStream>
#include <QFileInfo>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 2) {

      qWarning("Usage: owner file");
      return 1;
  }

  QString filename = argv[1];

  QFileInfo fileinfo{filename};

  QString group = fileinfo.group();
  QString owner = fileinfo.owner();

  out << "Group: " << group << endl;
  out << "Owner: " << owner << endl;

  return 0;
}

这个例子打印给定文件的拥有者和主组。

QFileInfo fileinfo{filename};

创建了QFileInfo类的实例。其参数是作为命令行参数给出的文件名。

QString group = fileinfo.group();

使用QFileInfo的group方法确定文件的主组。

QStringowner= fileinfo.owner();

使用QFileInfo的owner方法确定文件的拥有者。

$ touch myfile

$ ./ownergroup myfile

Group: janbodnar

Owner: janbodnar

Qt5文件最后阅读和最后修改时间

文件存储有关最后一次阅读或修改的信息。为了获取这些信息,我们使用QFileInfo类。

file_times.cpp
#include <QTextStream>
#include <QFileInfo>
#include <QDateTime>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 2) {

      qWarning("Usage: file_times file");
      return 1;
  }

  QString filename = argv[1];

  QFileInfo fileinfo{filename};

  QDateTime last_rea = fileinfo.lastRead();
  QDateTime last_mod = fileinfo.lastModified();

  out << "Last read: " << last_rea.toString() << endl;
  out << "Last modified: " << last_mod.toString() << endl;

  return 0;
}

这个示例打印出的最后阅读和最后修改的时间是2022年1月6日

QFileInfo fileinfo{filename};

创建QFileInfo对象。

QDateTime last_rea = fileinfo.lastRead();

lastRead方法返回文件最后一次被读取(访问)的日期和时间。

QDateTime last_mod = fileinfo.lastModified();

lastModified方法返回文件最后一次被修改的日期和时间。

$ ./filetimes Makefile

Last read: Sun Dec 6 12:46:11 2020

Last modified: Sun Dec 6 12:46:10 2020

Qt5与目录一起工作

QDir类具有处理目录的方法。

dirs.cpp
#include <QTextStream>
#include <QDir>

int main(void) {

  QTextStream out{stdout};
  QDir dir;

  if (dir.mkdir("mydir")) {

    out << "mydir successfully created" << endl;
  }

  dir.mkdir("mydir2");

  if (dir.exists("mydir2")) {

    dir.rename("mydir2", "newdir");
  }

  dir.mkpath("temp/newdir");

  return 0;
}

在这个例子中,我们介绍了四种处理目录的方法。

if (dir.mkdir("mydir")) {

out << "mydir successfully created" << endl;

}

mkdir方法创建目录。如果目录成功创建,它将返回true。

if (dir.exists("mydir2")) {

dir.rename("mydir2", "newdir");

}

exists检查目录是否存在。

rename方法重命名目录。

dir.mkpath("temp/newdir");

mkpath一次创建新目录和所有必要的父目录。

Qt5特殊路径

在文件系统中有一些特殊的路径,例如主目录或根目录。使用 QDir 类获取系统中的特殊路径。

special_paths.cpp

#include <QTextStream>
#include <QDir>

int main(void) {

  QTextStream out{stdout};

  out << "Current path:" << QDir::currentPath() << endl;
  out << "Home path:" << QDir::homePath() << endl;
  out << "Temporary path:" << QDir::tempPath() << endl;
  out << "Rooth path:" << QDir::rootPath() << endl;

  return 0;
}

这个示例输出四个特殊路径。

out << "Current path:" << QDir::currentPath() << endl;

使用 QDir::currentPath 方法获取当前工作目录。

out << "Home path:" << QDir::homePath() << endl;

使用 QDir::homePath 方法返回主目录。

out << "Temporary path:" << QDir::tempPath() << endl;

使用 QDir::tempPath 方法获取临时目录。

out << "Rooth path:" << QDir::rootPath() << endl;

使用 QDir::rootPath 方法返回根目录。

$ ./specialpaths

Current path:/home/janbodnar/Documents/prog/qt5/files/specialpaths

Home path:/root

Temporary path:/tmp

Rooth path:/

Qt5 文件路径

一个文件由其名称和路径标识,路径由文件名、基本名称和后缀组成。

file_path.cpp
#include <QTextStream>
#include <QFileInfo>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 2) {

      out << "Usage: file_times file" << endl;
      return 1;
  }

  QString filename = argv[1];

  QFileInfo fileinfo{filename};

  QString absPath = fileinfo.absoluteFilePath();
  QString baseName = fileinfo.baseName();
  QString compBaseName = fileinfo.completeBaseName();
  QString fileName = fileinfo.fileName();
  QString suffix = fileinfo.suffix();
  QString compSuffix = fileinfo.completeSuffix();

  out << "Absolute file path: " << absPath << endl;
  out << "Base name: " << baseName << endl;
  out << "Complete base name: " << compBaseName << endl;
  out << "File name: " << fileName << endl;
  out << "Suffix: " << suffix << endl;
  out << "Whole suffix: " << compSuffix << endl;

  return 0;
}

在这个例子中,我们使用了多个方法来打印给定文件名的文件路径及其各部分。

QFileInfo fileinfo{filename};

使用QFileInfo类来标识文件路径。

QString absPath = fileinfo.absoluteFilePath();

absoluteFilePath方法返回包括文件名在内的绝对路径。

QString baseName = fileinfo.baseName();

baseName方法返回基本名称——文件名不包含路径部分的名称。

QString compBaseName = fileinfo.completeBaseName();

completeBaseName方法返回完整的基本名称——文件名中最后一个点字符之前的所有字符。

QString fileName = fileinfo.fileName();

fileName方法返回文件名,即基本名称和扩展名。

QString suffix = fileinfo.suffix();

suffix方法返回文件扩展名,即文件名中最后一个点字符之后的所有字符。

QString compSuffix = fileinfo.completeSuffix();

文件扩展名可能由几部分组成;

completeSuffix方法返回第一个点字符之后的所有字符。

$ ./filepath ~/Downloads/qt-everywhere-opensource-src-5.5.1.tar.gz

Absolute file path: /home/janbodnar/Downloads/qt-everywhere-opensource-src-5.5.1.tar.gz

Base name: qt-everywhere-opensource-src-5

Complete base name: qt-everywhere-opensource-src-5.5.1.tar

File name: qt-everywhere-opensource-src-5.5.1.tar.gz

Suffix: gz

Whole suffix: 5.1.tar.gz

Qt5文件权限

文件系统中的文件有一套保护机制。文件被赋予标志,确定谁可以访问和修改它们。

QFile::permissions方法返回文件的枚举OR标志。

permissions.cpp
#include <QTextStream>
#include <QFile>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 2) {

      out << "Usage: permissions file" << endl;
      return 1;
  }

  QString filename = argv[1];

  auto ps = QFile::permissions(filename);

  QString fper;

  if (ps & QFile::ReadOwner) {

      fper.append('r');
  } else {
      fper.append('-');
  }

  if (ps & QFile::WriteOwner) {

      fper.append('w');
  } else {
      fper.append('-');
  }

  if (ps & QFile::ExeOwner) {

      fper.append('x');
  } else {
      fper.append('-');
  }

  if (ps & QFile::ReadGroup) {

      fper.append('r');
  } else {
      fper.append('-');
  }

  if (ps & QFile::WriteGroup) {

      fper.append('w');
  } else {
      fper.append('-');
  }

  if (ps & QFile::ExeGroup) {

      fper.append('x');
  } else {
      fper.append('-');
  }

  if (ps & QFile::ReadOther) {

      fper.append('r');
  } else {
      fper.append('-');
  }

  if (ps & QFile::WriteOther) {

      fper.append('w');
  } else {
      fper.append('-');
  }

  if (ps & QFile::ExeOther) {

      fper.append('x');
  } else {
      fper.append('-');
  }

  out << fper << endl;

  return 0;
}

此示例为给定的文件生成类Unix的权限列表。有三种可能的用户类型:拥有者、文件所属的组和其余用户,称为其他人。前三个位置属于文件所有者,接下来的三个位置属于文件组,最后三个字符属于其他人。有四种权限:读取(r)、写入或修改(w)、执行(x)和没有权限(-)。

auto ps = QFile::permissions(filename);

使用QFile::permissions方法,获取权限枚举。

QString fper;

根据给定权限动态构建字符串。

if (ps & QFile::ReadOwner) {

fper.append('r');

} else {

fper.append('-');

}

使用&运算符确定返回的枚举是否包含QFile::ReadOwner标志。

$ ./permissions Makefile

rw-rw-r--

文件的所有者和所属用户组有读取和修改文件的权限。其他用户有读取文件的权限。由于文件不是可执行文件,因此没有执行文件的权限。

Qt5列出目录内容

在下面的示例中,我们显示给定目录的内容。

list_dir.cpp
#include <QTextStream>
#include <QFileInfo>
#include <QDir>

int main(int argc, char *argv[]) {

  QTextStream out{stdout};

  if (argc != 2) {

      qWarning("Usage: list_dir directory");
      return 1;
  }

  QString directory = argv[1];

  QDir dir{directory};

  if (!dir.exists()) {

      qWarning("The directory does not exist");
      return 1;
  }

  dir.setFilter(QDir::Files | QDir::AllDirs);
  dir.setSorting(QDir::Size | QDir::Reversed);

  QFileInfoList list = dir.entryInfoList();

  int max_size = 0;

  for (QFileInfo finfo: list) {

      QString name = finfo.fileName();
      int size = name.size();

      if (size > max_size) {

          max_size = size;
      }
  }

  int len = max_size + 2;

  out << QString("Filename").leftJustified(len).append("Bytes") << endl;

  for (int i = 0; i < list.size(); ++i) {

    QFileInfo fileInfo = list.at(i);
    QString str = fileInfo.fileName().leftJustified(len);
    str.append(QString("%1").arg(fileInfo.size()));
    out << str << endl;
  }

  return 0;
}

为了列出目录的内容,我们使用QDir类及其entryInfoList方法。文件列表按大小的相反顺序排序,并整齐地排列。有两列; 第一列包含文件名,第二列包含文件大小。

QDir dir{directory};

创建一个具有给定目录名称的QDir对象。

dir.setFilter(QDir::Files | QDir::AllDirs);

setFilter方法指定entryInfoList方法应返回的文件类型。

dir.setSorting(QDir::Size | QDir::Reversed);

setSorting方法指定entryInfoList方法使用的排序顺序。

QFileInfoList list = dir.entryInfoList();

entryInfoList方法返回目录中所有文件和目录的QFileInfo对象列表,根据过滤和排序方法进行过滤和排序。 QFileInfoList是QList<QFileInfo>的同义词。

for (QFileInfo finfo: list) {

QString name = finfo.fileName();

int size = name.size();

if (size > max_size) {

max_size = size;

}

}

我们遍历列表并确定最大文件名大小。此信息需要用于整齐地组织输出。

int len = max_size + 2;

我们为列的长度额外增加两个空间。

out << QString("Filename").leftJustified(len).append("Bytes") << endl;

在此处,我们打印列名。leftJustified方法返回给定大小的字符串,其字符串左对齐,并使用填充字符(默认为空格)填充到其右侧。

for (int i = 0; i < list.size(); ++i) {

QFileInfo fileInfo = list.at(i);

QString str = fileInfo.fileName().leftJustified(len);

str.append(QString("%1").arg(fileInfo.size()));

out << str << endl;

}

我们遍历文件列表并打印它们的名称和尺寸。第一列是左对齐的,必要时用空格填充;第二列是简单地附加到行尾。

$ ./list_dir .

Filename Bytes

list_dir.pro 291

list_dir.cpp 1092

.. 4096

. 4096

list_dir.o 10440

list_dir 19075

Makefile 28369

这是该例子的输出样本。

在本章中,我们在Qt5中处理了文件和目录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值