Qt5 files and directories
last modified October 18, 2023
In this part of the Qt5 C++ programming tutorial, we work with files and directories.
QFile
, QDir
, and QFileInfo
are
fundamental classes for working with files in Qt5. QFile
provides
an interface for reading from and writing to files. QDir
provides
access to directory structures and their contents. QFileInfo
provides system-independent file information, including file's name and position
in the file system, access time and modification time, permissions, or file
ownership.
Qt5 file size
In the next example, we determine the size of a file.
#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; }
The size of the file is determined with the QFileInfo's
size
method.
QString filename = argv[1];
The name of the file is passed as an argument to the program.
QFile f{filename}; if (!f.exists()) { qWarning("The file does not exist"); return 1; }
The existence of the file is checked with the exists
method of the
QFile
class. If it does not exist, we issue a warning and terminate
the program.
QFileInfo fileinfo{filename};
An instance of the QFileInfo
is created.
qint64 size = fileinfo.size();
The file size is determined with the size
method. The
qint64
is a type guaranteed to be 64-bit on all platforms supported
by Qt.
QString str = "The size is: %1 bytes"; out << str.arg(size) << endl;
The outcome is printed to the console.
$ ./filesize Makefile The size is: 19993 bytes
Qt5 read file
In order to read the contents of a file, we must first open the file for reading. Then an input file stream is created; from this stream, the data is read.
sky blue cloud falcon forest lake cup bear wolf
We have a sample text file.
#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; }
The example reads data from the words.txt
file.
QFile f{"words.txt"};
An instance of the QFile
object is created. The QFile
automatically closes the file when it goes out of scope.
if (!f.open(QIODevice::ReadOnly)) { qWarning("Cannot open file for reading"); return 1; }
The QFile's
open
method opens the file in the
read-only mode. If the method fails, we issue a warning and terminate the
program.
QTextStream in{&f};
An input stream is created. The QTextStream
receives the file
handle. The data will be read from this stream.
while (!in.atEnd()) { QString line = in.readLine(); out << line << endl; }
In the while loop we read the file line by line until the end of the file.
The atEnd
method returns true if there is no more data to be read
from the stream. The readLine
method reads one line from the
stream.
$ ./readfile sky blue cloud falcon forest lake cup bear wolf
Qt5 write to file
In order to write to a file, we open the file in the write mode, create an output stream directed to the file, and use a write operator to write to that stream.
#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; }
The example writes the names of five Linux distributions to the file name called
distrost.txt
.
QString filename = "distros.txt"; QFile f{filename};
The QFile
object is created with the provided file name.
if (f.open(QIODevice::WriteOnly)) {
With the open
method, we open the file in the write-only method.
QTextStream out{&f};
This line creates a QTextStream
that operates on a file handle.
In other words, the stream of data to be written is directed to the file.
out << "Xubuntu" << endl; out << "Arch" << endl; out << "Debian" << endl; out << "Redhat" << endl; out << "Slackware" << endl;
The data is written with the << operator.
$ ./writefile $ cat distros.txt Xubuntu Arch Debian Redhat Slackware
Qt5 copy file
When we copy a file, we create an exact reproduction of the file with a different name or in a different place of the filesystem.
#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; }
The example creates a copy of the provided file with the
QFile::copy
method.
if (argc != 3) { qWarning("Usage: copyfile source destination"); return 1; }
The program takes two parameters; if they are not given, it ends with a warning message.
QString src = argv[1];
From the command line arguments of the program, we get the name of the source file.
if (!QFile{src}.exists()) { qWarning("The source file does not exist"); return 1; }
We check for the existence of the source file with the QFile's
exists
method. If it does not exist, we terminate the program with
a warning message.
QString dest(argv[2]);
We get the destination file name.
QFile::copy(src, dest);
The source file is copied with the QFile::copy
method. The first
parameter is the source file name, the second parameter is the destination file
name.
Qt5 file owner and group
Each file has a user who is its owner. A file also belongs to a group of users for better management and protection of files.
#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; }
The example prints the owner and the primary group of the given file.
QFileInfo fileinfo{filename};
An instance of the QFileInfo
class is created. Its parameter
is the file name given as a command line argument.
QString group = fileinfo.group();
The primary group of the file is determined with the QFileInfo's
group
method.
QString owner = fileinfo.owner();
The owner of the file is determined with the QFileInfo's
owner
method.
$ touch myfile $ ./ownergroup myfile Group: janbodnar Owner: janbodnar
Qt5 last read, last modified
Files store information about the last time they were read or modified. To get
this information, we use the QFileInfo
class.
#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; }
The example prints the last read and last modified time.
QFileInfo fileinfo{filename};
The QFileInfo
object is created.
QDateTime last_rea = fileinfo.lastRead();
The lastRead
method returns the date and time when the file was
last read (accessed).
QDateTime last_mod = fileinfo.lastModified();
The lastModified
method returns the date and time when the file was
last modified.
$ ./filetimes Makefile Last read: Sun Dec 6 12:46:11 2020 Last modified: Sun Dec 6 12:46:10 2020
Qt5 working with directories
The QDir
class has methods for working with directories.
#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; }
In the example, we present four methods for working with directories.
if (dir.mkdir("mydir")) { out << "mydir successfully created" << endl; }
The mkdir
method creates a directory. It returns true if the
directory was successfully created.
if (dir.exists("mydir2")) { dir.rename("mydir2", "newdir"); }
The exists
checks for the existence of a directory.
The rename
method renames the directory.
dir.mkpath("temp/newdir");
The mkpath
creates a new directory and all necessary parent
directories in one shot.
Qt5 special paths
There are some special paths in the filesystem; for instance a home diretory
or a root directory. The QDir
class is used to get the special
paths in the system.
#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; }
The example prints four special paths.
out << "Current path:" << QDir::currentPath() << endl;
The current working directory is retrieved with the
QDir::currentPath
method.
out << "Home path:" << QDir::homePath() << endl;
The home directory is returned with the QDir::homePath
method.
out << "Temporary path:" << QDir::tempPath() << endl;
The temporary directory is retrieved with the QDir::tempPath
method.
out << "Rooth path:" << QDir::rootPath() << endl;
The root directory is returned by the QDir::rootPath
method.
$ ./specialpaths Current path:/home/janbodnar/Documents/prog/qt5/files/specialpaths Home path:/root Temporary path:/tmp Rooth path:/
Qt5 file path
A file is identified by its name and path; a path consists of a file name, a base name, and a suffix.
#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; }
In the example, we use several methods to print the file path and its parts of the given file name.
QFileInfo fileinfo{filename};
The file path is identified using the QFileInfo
class.
QString absPath = fileinfo.absoluteFilePath();
The absoluteFilePath
method returns an absolute path including the
file name.
QString baseName = fileinfo.baseName();
The baseName
method returns the base name—the name of the file
without the path.
QString compBaseName = fileinfo.completeBaseName();
The completeBaseName
method returns the complete base name—all
characters in the file up to (but not including) the last dot character.
QString fileName = fileinfo.fileName();
The fileName
method returns the file name, which is the base
name and the extension.
QString suffix = fileinfo.suffix();
The suffix
method returns the file ending, which consists of all
characters in the file after (but not including) the last dot character.
QString compSuffix = fileinfo.completeSuffix();
A file ending may consist of several parts; the completeSuffix
method returns all characters in the file after (but not including) the first
dot character.
$ ./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 file permissions
Files in the filesystem have a system of protection. Files are given flags which
determine who can access and modify them. The QFile::permissions
method returns an enumeration of OR-ed flags for the file in question.
#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; }
The example produces a Unix-like list of permissions for the given file. There are tree kinds of possible users: owner, the group where the file belongs, and the rest of the users referred as others. The first three positions belong to the owner of the file, the next three positions to the file's group, and the last three characters belong to the others. There are four kinds of rights: reading (r), writing or modifying (w), executing (x), and no rights (-).
auto ps = QFile::permissions(filename);
With the QFile::permissions
method, we get the enumeration of
permission flags.
QString fper;
This string is dynamically built based on the given permissions.
if (ps & QFile::ReadOwner) { fper.append('r'); } else { fper.append('-'); }
We use the & operator to determine whether the returned enumeration
consists of the QFile::ReadOwner
flag.
$ ./permissions Makefile rw-rw-r--
The owner and the group of users where the file belongs have the right to read the file and modify it. Other users have the right to read the file. Since the file is not an executable, there are no rights to execute the file.
Qt5 list directory contents
In the following example, we display the contents of the given directory.
#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; }
To list the contents of a directory, we use the QDir
class and its
entryInfoList
method. The list of the files is reversely sorted by
its size and neatly lined up. There are two columns; the first column contains
file names and the second column file sizes.
QDir dir{directory};
A QDir
object with the given directory name is created.
dir.setFilter(QDir::Files | QDir::AllDirs);
The setFilter
method specifies the kind of files that should be
returned by the entryInfoList
method.
dir.setSorting(QDir::Size | QDir::Reversed);
The setSorting
method specifies the sort order used by the
entryInfoList
method.
QFileInfoList list = dir.entryInfoList();
The entryInfoList
method returns a list of QFileInfo
objects for all the files and directories in the directory, filtered and ordered
by the filtering and ordering methods. QFileInfoList
is a synonym
for QList<QFileInfo>
.
for (QFileInfo finfo: list) { QString name = finfo.fileName(); int size = name.size(); if (size > max_size) { max_size = size; } }
We go through the list and determine the maximum file name size. This information is needed to organize the output neatly.
int len = max_size + 2;
We give additional two spaces to the length of a column.
out << QString("Filename").leftJustified(len).append("Bytes") << endl;
Here we print the column names. The leftJustified
method returns a
string of the given size, whose string is left justified and padded by the fill
character (defaults to space) to its right.
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; }
We go through the list of files and print their names and sizes. The first column is left justified and padded with spaces as necessary; the second column is simply appended and the end of the line.
$ ./list_dir . Filename Bytes list_dir.pro 291 list_dir.cpp 1092 .. 4096 . 4096 list_dir.o 10440 list_dir 19075 Makefile 28369
This is a sample output of the example.
In this chapter, we worked with files and directories in Qt5.