Files are a specialization of a generalized notion—that of a byte stream that resides somewhere else. Qt encapsulates the more generalized notion of byte streams in its QIODevice
class, which is the parent class for QFile
as well as network I/O classes such as QTcpSocket
. We don't directly create a QIODevice
instance, of course, but instead create a subclass such as QFile
and then work with the QFile
instance directly to read from and write to the file.
To begin working with a file, we first must open it using the open
method. The open
method takes a single argument, the manner in which the file should be opened, a bitwise combination of the following:
QIODevice::ReadOnly
: This is used for read-only accessQIODevice::WriteOnly
: This is used for write-only accessQIODevice::ReadWrite
: This is used for read-and-write accessQIODevice::Append
: This is used to only append to the fileQIODevice::Truncate
: This is used to truncate the file, discarding all previous contents before writingQIODevice::Text
: This is used to treat the file as text, converting new-line characters to the platform representation during reading and writingQIODevice::Unbuffered
: This is used to bypass any buffering of the input and outputThese flags can be combined using the bitwise binary-or operator, |
. For example, a common combination is QIODevice::ReadWrite | QIODevice::Text
to read and write a text file. In fact, QIODevice:ReadWrite
is defined as QIODevice::Read | QIODevice::Write
internally.
Once you open the file, you can read a number of bytes by calling the file's read
method and passing the number of bytes to read; the resulting QByteArray
object contains the data to read. Similarly, you can write QByteArray
by calling write
, or use the overloaded write
method that takes a constant char *
. In either case, write
also takes the number of bytes to write. If all you want to do is read the entire contents of a file into a single buffer, you can call readAll
, which returns QByteArray
of the entire contents of the file.
Some QIODevice
subclasses such as QFile
are seekable; that is, you can position the read/write cursor at any point in the file, or determine its position. You can use the seek
method to position the cursor at a particular position in the file, and pos
to obtain the current location of the file cursor. Note that other QIODevice
subclasses like those for network I/O don't support seek
and pos
, but fail gracefully if you attempt to use these methods.
If you want to peek at the data without actually moving the cursor, you can call peek
and pass the number of bytes to return; the result is a QByteArray
. Calling read
after peek
returns the same data, because peek
doesn't advance the cursor past the data you've peeked at. The peek
method is handy when creating a complex parser that needs to know about incoming data in more than one place of its implementation; you can peek at the data, make a decision about how to parse the data, and then call read
later to get the data.
To determine whether or not you're at the end of a file and there's no more data to read, you can call atEnd
, which returns true if there is no more data to read. If you want to know how many bytes there are in the file, we can call bytesAvailable
, which returns the number of bytes available for reading (if known; a network socket might not carry that information, of course).
When working with files, we often need to work with directories as well. The QDir
class lets us examine the contents of a directory, determine whether a file or directory exists or not, and remove a file or directory. One thing to note is that regardless of the directory separator path used by the host platform, Qt always uses a forward slash /
to denote directories, so even if we're writing a Qt program for Windows, we use forward slashes, not back slashes. This makes it easy to write cross-platform compatible code that runs on both Windows and Linux without the need to use special case for the directory handling code.
First, create an instance of QDir
by passing a file path; after that, you can do the following with it:
absolutePath
cd
entryInfoList
exists
isRoot
remove
and passing the name of the file to remove
rename
rmdir
and passing the name of the directory to remove
==
and !=
operatorsOf course, locations of files, such as application preferences and/or temporary files, differ from platform to platform; the QStandardPaths
class has a static method standardLocations
that returns a path to the kind of storage we're looking for. To use it, we pass a value from the QStandardPaths::StandardLocation
enumeration, which has values such as:
DesktopLocation
: This returns the desktop directoryDocumentsLocation
: This returns the documents directoryMusicLocation
: This returns the location of music on the filesystemPicturesLocation
: This returns the location of photos on the filesystemTempLocation
: This returns the path to store temporary filesHomeLocation
: This returns the path to the current user's home directoryDataLocation
: This returns a path to an application-specific directory for persistent dataCacheLocation
: This returns a path to where the application can cache dataConfigLocation
: This returns a path to where the application can store configuration settingsFor more information about files and network IO, see the Qt documentation at http://qt-project.org/doc/qt-5/io-functions.html.