Здравствуйте.
На сегодняшний день подавляющее большинство компьютерных программ работают с файлами, а поэтому важно уметь пользоваться функциями или классами, которые позволяют открывать и закрывать, записывать и считывать информацию из файлов. В этой статье я немного расскажу о файлах и о классе QFile, а также покажу пример использования этого класса.
Файл, полные и относительные имена файлов
Файл — это именованная область данных, которая хранится на накопителе информации. То есть понятно, что на накопителе есть участок памяти, который содержит последовательность бит, у этого участка есть своё уникальное имя(пример: /home/nick/Desktop/file.txt или C:\\Downloads\file.txt — это полные имена файлов). По имени можно обращаться к этому участку памяти.
Существует такое понятие, как относительное имя файла. Относительное имя файла не содержит полного пути к нему. Его имя относительно к текущей рабочей директории, например из которой запущена программа, которая работает с файлами.
. — это ссылка, которая содержит адрес на текущую директорию
.. — это ссылка, которая содержит адрес на предыдущую директорию
Если мы хотим обратиться к файлу /text.txt, находясь в директории /etc/, то необходимо писать ../text.txt
Если к файлу в текущей директории, то text.txt или ./text.txt
Обычно, когда говорят об имени файла, то подразумевают ту часть, где опущен полный путь к нему, т.е. просто file.txt. Путь к файлу и полное имя файл понятия взаимозаменяемые.
Более подробную информацию о файлах можно найти в сети.
Обратите внимание, что на сайте имеется очень похожая статья статья про реализацию чтения из файлов на C++, но без использования фреймворка Qt.
QFile и примеры использования
Класс QFile наследует класс QIODevice, который для работы с файлами предоставляет методы: открытия и закрытия файлов, для записи и чтения из файла, для создания и удаления файлов.
Чтобы создать объект для работы с файлом, нужно передать в конструктор имя файла.
1 |
QFile file("myfile.txt"); |
Можно не передавать имя файла в конструктор, а установить его в объекте методом setName().
1 2 |
QFile file; file.setName("myfile.txt"); |
Часто при работе с файлами требуется узнать, открыт ли файл. Метод QIODevice::isOpen() возвращает значение true, если файл открыт и false в противном случае. А так как QFile унаследован от него, то мы можем проверить, открыт ли файл.
1 2 3 4 5 |
QFile file("myfile.txt"); if(file.isOpen) { qDebug() << "File is open"; } |
Для закрытия файла нужно вызвать метод QFile::close()
1 |
file.close(); |
Обратите внимание, что данные сразу не записываются в файл на накопителе, они записываются в буфер в оперативной памяти. После закрытия файла данные из буфера записываются в файл на носителе. Это сделано для того, чтобы не нагружать жесткий диск или любой другой тип накопителя, на котором находится файл. Информацию из буфера в файл можно записать принудительно без закрытия файла, вызвав метод QFile::flush()
1 |
file.flush() |
Существует очень полезный метод QFile::exists(). Он принимает на вход строку с именем файла и возвращает значение true, если такой файл существует. Существует статический и нестатический методы. Для работы со статическим методом необходимо указать имя файла.
1 2 3 4 |
if(QFile::exists("myfile.txt")) { qDebug() << "Файл существует"; } |
Для работы с нестатическим достаточно просто его вызвать.
1 2 3 4 |
if(file.exists()) { qDebug() << "Файл существует"; } |
Для возможности записи или чтения необходимо открыть файл с указанием флага чтения QIODevice::ReadOnly или записи QIODevice::WriteOnly. Пример открытия файла для записи:
1 2 3 4 5 |
QFile file("myfile.txt"); if (!file.open(QIODevice::WriteOnly)) { qDebug() << "Ошибка при открытии файла"; } |
Есть разные способы чтения из фалов и записи. Можно считать или записать всю информацию за один раз, а можно по одному символу или блоками.
Для примера напишем программу, которая считывает из файла блок из первых 10-ти символов, а потом вставляет в другой файл.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <QCoreApplication> #include <QFile> //Подключаем для работы с классом QFile int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QFile fileIn("filein.txt"); QFile fileOut("fileout.txt"); if(fileIn.open(QIODevice::ReadOnly) && fileOut.open(QIODevice::WriteOnly)) { //Если первый файл открыт для чтения, а второй для записи успешн QByteArray block = fileIn.read(10); // Считываем 10 байт в массив block из filein.txt fileOut.write(block); // Записываем 10 байт в файл fileout.txt fileIn.close(); // Закрываем filein.txt fileOut.close(); // Закрываем fileout.txt } return a.exec(); } |
Я создал файл filein.txt и внёс в него произвольный текст с помощью текстового редактора. После запуска программы я открыл filein.txt и fileout.txt в текстовом редакторе.
Можно было считать все байты, тогда всё содержимое первого файла копировалось во второй. Для полного считывания строку
1 |
QByteArray block = fileIn.read(10); |
Нужно заменить на строку
1 |
QByteArray block = fileIn.readAll(); |
В результате программа считает все байты в массив block, а после запишет их во второй файл.
Мы можем записывать информацию в файл строками, для этого его нужно открыть в текстовом режиме.
1 |
fileOut.open(QIODevice::WriteOnly | QIODevice::Text); |
После передать адрес в конструктор нового объекста класса QTextStream.
1 |
QTextStream writeStream(&fileOut); |
А далее при помощи оператора << посылать строки в поток записи.
Пример программы, в которая записывает в файл fileout.txt строку «Text, text, text.»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <QCoreApplication> #include <QFile> // Подключаем класс QFile #include <QTextStream> // Подключаем класс QTextStream int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QFile fileOut("fileout.txt"); // Связываем объект с файлом fileout.txt if(fileOut.open(QIODevice::WriteOnly | QIODevice::Text)) { // Если файл успешно открыт для записи в текстовом режиме QTextStream writeStream(&fileOut); // Создаем объект класса QTextStream // и передаем ему адрес объекта fileOut writeStream << "Text, text, text."; // Посылаем строку в поток для записи fileOut.close(); // Закрываем файл } return a.exec(); } |
Содержимое fileout.txt после запуска программы
Запись в конец файла
Предыдущий метод полностью перезаписывал данные в файле, то есть очищал всё его содержимое и записывал новые данные. Перезаписи можно избежать и записывать новые данные в конец файла.
Флаг QIODevice::Append помещает указатель для записи (seek) в конец файла, в итоге входящий поток записывается сразу после имеющейся информации в файле. Пример фрагмента использования:
1 |
fileOut.open(QIODevice::Append | QIODevice::Text); |
В примере вместо QIODevice::WriteOnly используется QIODevice::Append. Если сделать такое изменение в предыдущей программе, то после нескольких запусков в файле fileout.txt будет храниться строчка
Text, text, text.Text, text, text.Text, text, text.
Итак, мы рассмотрели основные методы для работы с файлами. Более подробную информацию обо всех методах класса QFile и QIODevice можно найти в официальной документации Qt и в сети.
Помогло разобраться с классом, хорошо изложено! 🙂
Не понимаю, где будут сохраняться эти файлы
Ну пойми
если просто имя — в директорию с проектом
если полный путь — в директорию указанную в пути