Qt существует ли файл
Редко встречается приложение, которое не обращается к файлам. Работа с директориями (папками, в терминологии ОС Windows) и файлами — это та область, в которой не все операции являются платформонезависимыми,
поэтому Qt предоставляет свою собственную поддержку этих операций, состоящую из следующих классов:
QDir — для работы с директориями;
QFile — для работы с файлами;
QFileInfо — для получения файловой информации;
QIODevice — абстрактный класс для ввода/вывода;
QBuffer — для эмуляции файлов в памяти компьютера.
Ввод/вывод. Класс QIODevice
QIODevice — это абстрактный класс, обобщающий устройство ввода/вывода, который содержит виртуальные методы для открытия и закрытия устройства ввода/вывода, а также для чтения и записи блоков данных или отдельных символов.
Реализация конкретного устройства происходит в унаследованных классах.
В Qt есть четыре класса, наследующие класс QIODevice :
QFile — класс для проведения операций с файлами;
QBuffer — позволяет записывать и считывать данные в массив QByteArray , как будто бы это устройство или файл;
QAbstractSocket — базовый класс для сетевой коммуникации посредством сокетов.
QProcess — этот класс предоставляет возможность запуска процессов с дополнительными аргументами и позволяет обмениваться информацией с этими процессами посредством методов, определенных в QIODevice .
Для работы с устройством его необходимо открыть в одном из режимов, определенных В заголовочном файле класса QIODevice :
QIODevice::NotOpen — устройство не открыто (это значение не имеет смысла передавать в метод open() );
QIODevice::ReadOnly — открытие устройства только для чтения данных;
QIODevice::writeOnly — открытие устройства только для записи данных;
QIODevice::ReadWrite — открытие устройства для чтения и записи данных (то же, что и IO_ReadOnly | IO_WriteOnly );
QIODevice::Append — открытие устройства для добавления данных;
QIODevice::Unbuffered — открытие для непосредственного доступа к данным, в обход промежуточных буферов чтения и записи;
QIODevice::Text — применяются преобразования символов переноса строки в зависимости от платформы. Для ОС Windows, например — \r\n, а для MacOS X и
QIODevice::Truncate — все данные устройства, по возможности, должны быть удалены при открытии.
Для того чтобы в любой момент времени исполнения программы узнать, в каком из режимов было открыто устройство, нужно вызвать метод openMode() .
Считывать и записывать данные можно с помощью
методов read() и write() соответственно. Для чтения всех данных сразу определен
метод readAll() , который возвращает их в объекте типа QByteArray . Строку или символ можно прочитать методами readLine() и getChar() соответственно.
В классе QIODevice определен метод для смены текущего положения seek() . Получить текущее положение можно вызовом метода pos() . Но не забывайте, что эти методы применимы только для прямого доступа к данным. При последовательном доступе, каким является сетевое соединение, они теряют смысл. Более того, в этом случае теряет смысл и метод size() , возвращающий размер данных устройства. Все эти операции применимы только
для QFile , QBuffer и QTemporaryFile .
Для создания собственного класса устройства ввода/вывода, для которого Qt не
предоставляет поддержки, необходимо унаследовать класс QIODevice и реализовать в нем методы readData() и writeData() . В большинстве случаев может потребоваться перезаписать методы open() , close() и atEnd() .
Благодаря интерфейсу класса QIODevice можно работать со всеми устройствами одинаково, при этом не имеет значения, является ли устройство файлом, буфером или другим устройством. Выведем на консоль данные из любого устройства.
void print(QIODevice *pdev)
char ch; QString str;
pdev->open(QIODevice::ReadOnly); for (; !pdev->atEnd();)
pdev->getChar(&ch); str += ch;
Класс QIODevice предоставляет ряд методов, с помощью которых можно получить информацию об устройстве ввода/вывода. Например, одни устройства могут только записывать информацию, другие — только считывать, а третьи способны делать и то, и другое. Чтобы узнать об этом, следует воспользоваться
методами isReadable() и isWriteable() .
Класс QFile унаследован от класса QIODevice . В нем содержатся методы для работы с файлами: открытия, закрытия, чтения и записи данных. Создать объект можно, передав в конструкторе строку, содержащую имя файла. Можно ничего не
передавать в конструкторе, а сделать это после создания объекта, вызовом метода setName() . Например:
В процессе работы с файлами иногда требуется узнать, открыт файл или нет. Для этого вызывается метод QIODevice::isOpen() , который вернет true , в том случае,
если файл открыт, иначе — false . Чтобы закрыть файл, нужно вызвать метод close() . С закрытием произведется запись всех данных буфера. Если
требуется произвести запись данных буфера в файл без его закрытия, то вызывается метод QFile::flush() .
Проверить, существует ли нужный вам файл, можно статическим
методом QFile::exists() . Этот метод принимает строку, содержащую полный или относительный путь к файлу. Если файл найден, то метод возвратит true , в противном случае — false . Для проведения этой операции существует и нестатический метод QFile::exists() .
Методы QIODevice::read() и QIODevice::write() позволяют считывать и записывать файлы блоками.
Продемонстрируем применение некоторых методов работы с файлами:
QFile file1( "file1.dat" );
QFile file2( "file2.dat" );
//Файл уже существует. Перезаписать?
qDebug() << "Ошибка открытия для чтения" ;
qDebug() << "Ошибка открытия для записи" ;
char a [1024]; while (!file1.atEnd())
int nBlocksize = file1.read(a, sizeof (a)); file2.write(a, nBlocksize);
Если требуется считать или записать данные за один раз, то используют методы QIODevice::write() и QIODevice::readAll() . Все данные можно считать в объект класса QByteArray , а потом записать из него в другой файл:
QFile file1( "file1.dat" );
QFile file2( "file2.dat" );
//Файл уже существует. Перезаписать?
qDebug() << "Ошибка открытия для чтения" ;
qDebug() << "Ошибка открытия для записи" ;
QByteArray a = file1.readAll(); file2.write(a);
Операция считывания всех данных сразу, в зависимости от размера файла, может занять много оперативной памяти, а значит, к этому следует прибегать только в случаях острой необходимости или в том случае, когда файлы занимают мало места. Расход памяти при считывании сразу всего файла можно значительно сократить при том условии, что файл содержит избыточную информацию. Тогда можно воспользоваться функциями сжатия qCompress() и qUncompress() , которые определены вместе с классом QByteArray . Эти функции получают, в качестве аргумента, объект класса QByteArray и возвращают, в качестве результата, новый объект класса QByteArray .
Для удаления файла класс QFile содержит статический метод remove() . В этот метод необходимо передать строку, содержащую полный или относительный путь удаляемого файла.
Класс QBuffer унаследован от QIODevice , и представляет собой эмуляцию файлов в памяти компьютера (memory mapped files). Это позволяет записывать информацию в оперативную память и использовать объекты как обычные файлы (открывать при помощи метода open() и закрывать методом close() ). При помощи методов write() и read() можно считывать и записывать блоки данных. Можно это так же сделать при помощи потоков, которые будут рассмотрены далее. Рассмотрим пример использования класса QBuffer:
out << QString( "Message" );
Как видно из этого примера, сами данные сохраняются внутри объекта
класса QByteArray . При помощи метода buffer() можно получить константную ссылку к внутреннему объекту QByteArray , а при помощи
метода setBuffer() можно устанавливать другой объект QByteArray для его использования в качестве внутреннего.
Класс QBuffer полезен для проведения операций кэширования. Например, можно считывать файлы растровых изображений в объекты класса QBuffer , а затем, по необходимости, получать данные из них.
Иногда приложению может потребоваться создать временный файл. Это может быть связано, например, с промежуточным хранением большого объема данных или передачей этих данных какой-либо другой программе.
Класс QTemporaryFile представляет реализацию для временных файлов. Этот класс самостоятельно создает себе имя с гарантией его уникальности, для того чтобы не возникало конфликтов, в результате которых могли бы пострадать уже существующие файлы. Сам файл будет расположен в каталоге для промежуточных данных, местонахождение которого можно получить вызовом
метода QDir :: tempPath (). С уничтожением объекта будет уничтожен и сам временный файл.
Разные платформы имеют разные способы представления путей. ОС Windows содержит буквы дисков, например: C:\Windows\System. UNIX использует root, например: /usr/bin. Обратите внимание, что для разделения имен директорий в обоих представлениях используются разные знаки. Для представления директорий в платформонезависимой форме Qt предоставляет класс QDir .
Для этих целей класс предоставляет целый ряд статических методов:
QDir :: current () — возвращает путь директории приложения;
QDir :: root () — возвращает root-директорию;
QDir :: drives ()—возвращает указатель на список объектов класса
QFileinfo с узловыми директориями (root). Для Windows это будут С:\, D:\ и т.
QDir :: home () — возвращает персональную директорию пользователя.
Класс QDir не предоставляет методов для определения текущего каталога приложения. Но если вам потребуется определить, из какого каталога было запущенно приложение, то следует воспользоваться
методом QApplication :: applicationDirPath (), либо QApplication :: applicationFilePath (),
возвращающим, в добавок ко всему, и имя приложения.
Существование директории можно проверить с помощью метода exists (). Чтобы перемещаться по директориям, можно использовать метод cd (), который принимает, в качестве параметра, абсолютный путь директории, и cdUp (). Вызов cd ("..") эквивалентен вызову метода cdUp ().
Для конвертирования относительного пути директории в абсолютный можно вызвать метод makeAbsolute ().
Для создания директории нужно вызвать метод mkdir (). В случае успешного проведения этой операции метод вернет значение true , в случае неудачи — false .
Если вам потребуется переименовать директорию, то воспользуйтесь методом rename (). В этот метод первым параметром нужно передать старый путь, а вторым — новый. Если операция будет проведена успешно, то метод вернет true , иначе — false .
Удаление директорий производится методом rmdir (), который получает путь, и в случае успеха возвращает true , а в случае неудачи — false .
При помощи класса QDir можно получить содержимое указанной директории. При этом допускается применять различные фильтры, чтобы исключить из списка не интересующие вас файлы. Для этих целей в классе определены методы entryList () и entryInfoList (). Первый возвращает список имен элементов ( QStringList ), а второй — информационный список ( QFileInfoList ). Если вам нужно узнать только количество элементов, находящихся в директории, то просто вызовите
Программа, показанная на рисунке, осуществляет рекурсивный поиск файлов в директории, указанной в текстовом поле Directory (Директория). Нажатие кнопки с растровым изображением откроет диалоговое окно выбора нужной директории. В текстовом поле Mask (Маска) задается фильтр для отображаемых файлов. Например, для отображения исходных файлов на языке C++ нужно задать в поле Mask (Маска) *. срр и *. h . После нажатия кнопки Find (Поиск) производится отображение файлов, в соответствии с заданными параметрами. Результаты отображаются в виджете многострочного текстового поля.
FileFinder::FileFinder(QWidget* pwgt/*= 0*/) : QWidget(pwgt)
= new QLineEdit( "*.cpp *.h" );
new QLabel( "&Directory" );
new QLabel( "&Mask" );
new QPushButton( "&Find" );
connect(pcmdDir, SIGNAL (clicked()), SLOT (slotBrowse())); connect(pcmdFind, SIGNAL (clicked()), SLOT (slotFind()));
QGridLayout* pgrdLayout = new QGridLayout; pgrdLayout->setMargin(5); pgrdLayout->setSpacing(15); pgrdLayout->addWidget(plblDir, 0, 0); pgrdLayout->addWidget(plblMask, 1, 0); pgrdLayout->addWidget(m_ptxtDir, 0, 1); pgrdLayout->addWidget(m_ptxtMask, 1, 1); pgrdLayout->addWidget(pcmdDir, 0, 2); pgrdLayout->addWidget(pcmdFind, 1, 2); pgrdLayout->addWidget(m_ptxtResult, 2, 0, 1, 3); setLayout(pgrdLayout);
В конструкторе класса FileFinder создаются виджеты однострочного и многострочного текстовых полей
(указатели m _ ptxtDir , m _ ptxtMask и m _ ptxtResult ). Первый виджет инициализируется абсолютным путем, возвращаемым методом QDir :: absolutePath (), который, в свою очередь, инициализируется значением текущей директории, возвращаемой методом QDir :: current () . Второй виджет инициализируется строкой, предназначенной для фильтрации найденных файлов. Для старта операции поиска и открытия диалогового окна выбора директории создаются две кнопки нажатия— указатели pcmdFind и pcmdDir , которые соединяются со слотами slotFind () и slotBrowse(). В конструкторе создаются два виджета надписей, а с помощью метода setBuddy () они ассоциируются с виджетами однострочных текстовых полей. Созданные виджеты размещаются в виде таблицы при помощи объекта класса QGridLayout .
QString str = QFileDialog::getExistingDirectory
"Select a Directory" ,
Метод slotBrowse (), который открывает диалоговое окно для выбора директории поиска. После закрытия этого окна директория записывается в текстовое поле Directory (Директория) с помощью метода setText ().
Метод slotFind () запускает операцию поиска и передает в метод start () выбранную пользователем директорию.
void FileFinder::start( const QDir& dir)
QStringList listFiles = dir.entryList(m_ptxtMask->text().split( " " ), QDir::Files);
QStringList listDir = dir.entryList(QDir::Dirs); foreach (QString subdir, listDir)
Процесс поиска заданных файлов может быть длительным, что может привести к "замиранию" графического интерфейса программы. Поэтому, для подавления этого нежелательного эффекта, при каждом вызове метода воспользуемся методом QApplication :: processEvent () и дадим возможность обработаться накопившимся событиям. В методе start о переменная listFiles получает список файлов текущей директории. Для этого в методе установлены два параметра. Первый представляет собой список шаблонов поиска, которые распространяются на имена и расширения файлов. В нашем случае мы преобразуем строку в список, разделив ее посредством пробелов, с помощью QString :: split (). Второй параметр ( QDir :: Files ) указывает на то, что список должен содержать только файлы. Элементы полученного списка добавляются в виджет многострочного текстового поля с помощью метода append (). По завершению работы цикла добавления, в метод entryList () передается параметр QDir :: Dirs для получения списка директорий. Для каждого из элементов списка, кроме "." и "..", вызывается метод start ().
Задача этого класса состоит в предоставлении информации о свойствах файла, например: имя, размер, время последнего изменения, права доступа и т. д. Объект класса QFileInfo создается передачей в его конструктор пути к файлу, но можно передавать и объекты класса QFile .
Файл или каталог?
Иногда необходимо убедиться, что исследуемый объект является каталогом, а не файлом и наоборот. Для этой цели существуют методы isFile () и isDir ().
В том случае, если объект является файлом, метод isFile () возвращает значение булевого типа true , иначе — false . Если объект является директорией, то метод isDir () возвращает true , иначе — false . Кроме этих методов,
класс QFileInfo содержит метод isSymLink (), возвращающий true , если объект является символьной ссылкой (symbolic link или shortcut в ОС Windows).
Символьные ссылки применяются в UNIX для обеспечения связи с файлами или каталогами. Создаются они при помощи команды "ln" с ключом "-s".
Путь и имя файла в Qt
Чтобы получить путь к файлу, нужно воспользоваться методом absoluteFilePath (). Для получения относительного пути к файлу следует использовать метод filePath (). Для получения имени файла нужно вызвать метод fileName (), который возвращает имя файла вместе с его расширением. Если нужно только имя файла, то следует вызвать метод baseName (). Для получения расширения используется
Информация о дате и времени файла в Qt
Иногда нужно узнать время создания файла, время его последнего изменения или чтения. Для этого класс QFileInfo предоставляет методы created (), lastModified () и lastRead () соответственно. Эти методы возвращают объекты класса QDateTime , которые можно преобразовать в строку методом toString (). Например:
//Дата и время создания файла fileInfo.created().toString();
//Дата и время последнего изменения файла fileInfo.lastModified().toString();
//Дата и время последнего чтения файла
Получение атрибутов файла в Qt
Атрибуты файла дают информацию о том, какие операции можно проводить с файлом.
Для их получения в классе QFileInfо существуют следующие методы:
isReadable () —возвращает true , если из указанного файла можно читать информацию;
isWriteable () —возвращает true , если в указанный файл можно записывать информацию;
isHidden () — возвращает true , если указанный файл является скрытым;
isExecutable () —возвращает true , если указанный файл можно исполнять. В ОС UNIX это определяется не на основании расширения файла, как привыкли считать программисты в DOS и ОС Windows, а посредством свойств самого файла.
Определение размера файла в Qt
Метод size () класса QFileInf о возвращает размер файла в байтах. Размер файлов редко отображается в байтах, чаще используются специальные буквенные обозначения, сообщающие об его размере. Например, для килобайта — это буква К, для мегабайта — М, для гигабайта — G, а для терабайта — Т. Следующая функция позволяет сопровождать буквенными обозначениями размеры, лежащие даже в терабайтном диапазоне (вполне возможно, что через несколько лет это будет обычный размер файла):
QString fileSize(qint64 nSize)
for (; nSize > 1023; nSize /= 1024, ++i) < >return QString().setNum(nSize) + "BKMGT" [i];
Объекты файлов, сами по себе, обладают только элементарными методами для чтения и записи информации. Использование потоков делает запись и считывание файлов более простым и гибким. Для файлов, содержащих текстовую информацию, следует использовать класс QTextStream , а для двоичных файлов —
Применение классов QTextStream и QDataStream такое же, как и для стандартного потока в языке C++ ( iostream ), с той лишь разницей, что они могут работать с объектами класса QIODevice . Благодаря этому, потоки можно использовать и для своих собственных классов, унаследованных от QIODevice .
Для записи данных в поток используется оператор <<, а для чтения данных из потока — >>.
На этом шаге рассмотрим класс QFile.
Класс QFile унаследован от класса QIODevice. В нем содержатся методы для работы с файлами: открытия, закрытия, чтения и записи данных. Создать объект можно, передав в конструкторе строку, содержащую имя файла. Можно ничего не передавать в конструкторе, а сделать это после создания объекта вызовом метода setName(). Например:
В процессе работы с файлами иногда требуется узнать, открыт файл или нет. Для этого вызывается метод QIODevice::isOpen(), который вернет значение true, если файл открыт, иначе — false.
Чтобы закрыть файл, нужно вызвать метод close(). С закрытием осуществляется запись всех данных буфера. Если требуется выполнить запись данных буфера в файл без его закрытия, то вызывается метод QFile::flush().
Проверить, существует ли нужный вам файл, можно статическим методом QFile::exists(). Этот метод принимает строку, содержащую полный или относительный путь к файлу. Если файл найден, то метод возвратит значение true, в противном случае — false. Для проведения этой операции существует и нестатический метод QFile::exists(), который проверяет существование файла, возвращаемого методом fileName().
Методы QIODevice::read() и QIODevice::write() позволяют считывать и записывать файлы блоками.
Если требуется считать или записать данные за один раз, то используют методы QIODevice::write() и QIODevice::readAll(). Все данные можно считать в объект класса QByteArray, а потом записать из него в другой файл.
Для удаления файла класс QFile содержит статический метод remove(). В этот метод необходимо передать строку, содержащую полный или относительный путь удаляемого файла.
Продемонстрируем применение некоторых методов работы с файлами. Рассмотрим следующий пример. Даны два файла f1.dat и f2.dat. Необходимо записать в файл f3.dat первые 5 символов из файла f1.dat, а затем первые 5 символов из файла f2.dat, и в завершении дописать содержимое файла f1.dat в конец файла f2.dat. Реализация этого примера приведена на рисунке 1.
QT операции с файлами (создание, копирование, запись, удаление)
В QT нам часто необходимо выполнять различные операции с файлами, такие как создание файлов, запись, копирование и удаление и т.д., все из которых используют класс QFile.
Класс QFile предоставляет интерфейс для чтения и записи файлов. В обычных условиях мы можем напрямую передать имя файла при вызове конструктора, что является более удобным методом. Или используйте QFile для создания объекта, а затем вызовите метод setFileName (), чтобы установить путь к файлу. Разделителем пути в имени файла должен быть '/', другие разделители не поддерживаются QFile.
QFile(const QString & name)
QFile(QObject * parent)
QFile(const QString & name, QObject * parent)
Общие функции QFile:
Название функции
Режим открытия файла:
Режим | Значение | Описание |
QIODevice::NotOpen | 0x0000 | Не открывать |
QIODevice::ReadOnly | 0x0001 | Режим только для чтения |
QIODevice::WriteOnly | 0x0002 | Режим только для записи, если файл не существует, файл будет создан автоматически |
QIODevice::ReadWrite | ReadOnly | WriteOnly | Методы чтения и письма |
QIODevice::Append | 0x0004 | Этот режим означает, что все данные записываются в конец файла. |
QIODevice::Truncate | 0x0008 | Перед открытием файла файл усекается, и все данные в исходном файле будут потеряны. |
QIODevice::Text | 0x0010 | При чтении флаг конца файла будет преобразован в «\ n»; при записи флаг конца файла будет преобразован в конец локальной кодировки, например в конец win32 ’\ r \ n’ |
QIODevice::UnBuffered | 0x0020 | Не кэшировать |
1. Создайте и откройте файл.
2. Определите, существует ли файл.
3. Скопируйте файлы.
4. Переименуйте файл.
5. Получить права пользователя на указанный файл, доступен ли он для чтения.
На этом уроке мы рассмотрим работу с файлами и каталогами в Qt5. Для этого мы будем использовать следующие классы:
QFile , QDir и QFileInfo — основные классы для работы с файлами в Qt5;
QFile — предоставляет интерфейс для чтения и записи информации в файлы;
QDir — обеспечивает доступ к структуре каталогов и к их содержимому;
QFileInfo — предоставляет информацию о файле, включая его имя и расположение в файловой системе, время доступа и изменения, имя владельца файла и текущие разрешения.
Размер файла
Для определения размера файла в классе QFileInfo предусмотрен метод size():
// Имя файла передается в качестве аргумента в нашу программу qWarning ( "The file does not exist" ) ; // если файл не найден, то выводим предупреждение и завершаем работу программы qint64 size = fileinfo . size ( ) ; // qint64 - это тип данных, который гарантированно будет 64-битным на всех платформах, поддерживаемых QtДля запуска программы проделайте следующие шаги:
ПОДГОТОВКА:
Шаг №1: Скомпилируйте вашу программу. Для этого выберите в меню "Сборка" > "Собрать всё" (или нажмите Ctrl+Shift+B ).
Шаг №2: Зайдите в папку, где лежит ваш Qt-проект (у меня он расположен в C:\dev\Qt_Project ).
Шаг №3: После выполнения первого шага у вас должна появиться еще одна папка, в которой будет создан исполняемый файл программы. Т.к. я использую компилятор MinGW 32-bit и режим компиляции Debug, то при компиляции проекта Qt автоматически создал папку build-My_QtApplication-Desktop_Qt_5_13_0_MinGW_32_bit-Debug .
Шаг №4: Зайдите в папку debug (она находится внутри папки, созданной на шаге №3).
Шаг №5: Найдите *.exe-файл вашей программы (у меня это file_size.exe ).
Шаг №6: Скопируйте этот файл в папку к соответствующему компилятору (напомню, т.к. я использовал компилятор MinGW 32-bit, то у меня этот путь выглядит следующим образом: C:\Soft\Qt\5.13.0\mingw73_32\bin ).
ЗАПУСК ПРОГРАММЫ:
Шаг №7: Откройте командную строку.
Шаг №8: Перейдите в папку, указанную в шаге №6 ( cd C:\Soft\Qt\5.13.0\mingw73_32\bin ).
Шаг №9: Запустите свою программу, передав ей в качестве параметра имя любого файла (у меня этим файлом оказалась эта же программа, поэтому в моем случае команда была следующей: file_size.exe file_size.exe ).
Результат выполнения программы:
Чтение содержимого файлов
Для того, чтобы прочитать содержимое файла, мы должны сначала открыть этот файл в режиме чтения, затем создать входящий файловый поток, из которого мы будем считывать данные. В примере, приведенном ниже, мы считываем данные из файла C:\colours.txt . Файл содержит названия семи цветов, вот его содержимое:
Red
Green
Black
Yellow
Purple
Blue
White
Читайте также: