Qfile как пользоваться
Перейти к содержимому

Qfile как пользоваться

  • автор:

Запись текста в QFile

Запись через QTextStream является более гибкой. Судя по справке её предпочтительнее использовать для записи текста. Но write может оказатся быстрее, т.к. не учавствует промежуточный класс.

29 мая 2018 в 8:43

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Задал как-то данный вопрос на английском Stack Overflow, опубликую здесь перевод ответа, может кому-нибудь пригодится.

QIODevice::write — низкоуровневый байтовый интерфейс для записи необработанных данных на устройство. QTextStream — высокоуровневый интерфейс для записи форматированного текста. Вероятно QTextStream реализован

Основной вариант использования QTextStream — запись строк класса QString . Текстовый поток конвертирует строку из UTF-16 в локальную кодировку, установленную по умолчанию (обычно 8-битную), или в любую другую кодировку, установленную через QTextStream::setCodec .

QTextStream почти наверняка работает медленнее, т.к. выполняет больше операций, однако в большинстве случаев разница в скорости с QIODevice::write будет незначительна. Если необходимо собрать большую строку из сырых данных вручную, то вероятно лучше использовать QIODevice::write . Если необходимо записать форматированный текст, в том числе QString , то вероятно более предпочтительным будет использование QTextStream .

QFile и файлы. Чтение и запись строк в файл.

Пингвин читает содержимое файла

Follow us on Twitter Follow us on rss

На сегодняшний день подавляющее большинство компьютерных программ работают с файлами, а поэтому важно уметь пользоваться функциями или классами, которые позволяют открывать и закрывать, записывать и считывать информацию из файлов. В этой статье я немного расскажу о файлах и о классе 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, который для работы с файлами предоставляет методы: открытия и закрытия файлов, для записи и чтения из файла, для создания и удаления файлов.

Чтобы создать объект для работы с файлом, нужно передать в конструктор имя файла.

QFile file("myfile.txt");

Можно не передавать имя файла в конструктор, а установить его в объекте методом setName().

QFile file; file.setName("myfile.txt");

Часто при работе с файлами требуется узнать, открыт ли файл. Метод QIODevice::isOpen() возвращает значение true, если файл открыт и false в противном случае. А так как QFile унаследован от него, то мы можем проверить, открыт ли файл.

QFile file(«myfile.txt»); if(file.isOpen)

Для закрытия файла нужно вызвать метод QFile::close()

file.close();

Обратите внимание, что данные сразу не записываются в файл на накопителе, они записываются в буфер в оперативной памяти. После закрытия файла данные из буфера записываются в файл на носителе. Это сделано для того, чтобы не нагружать жесткий диск или любой другой тип накопителя, на котором находится файл. Информацию из буфера в файл можно записать принудительно без закрытия файла, вызвав метод QFile::flush()

file.flush()

Существует очень полезный метод QFile::exists(). Он принимает на вход строку с именем файла и возвращает значение true, если такой файл существует. Существует статический и нестатический методы. Для работы со статическим методом необходимо указать имя файла.

if(QFile::exists(«myfile.txt»))

Для работы с нестатическим достаточно просто его вызвать.

if(file.exists())

Для возможности записи или чтения необходимо открыть файл с указанием флага чтения QIODevice::ReadOnly или записи QIODevice::WriteOnly. Пример открытия файла для записи:

QFile file(«myfile.txt»); if (!file.open(QIODevice::WriteOnly))

Есть разные способы чтения из фалов и записи. Можно считать или записать всю информацию за один раз, а можно по одному символу или блоками.

Для примера напишем программу, которая считывает из файла блок из первых 10-ти символов, а потом вставляет в другой файл.

#include #include //Подключаем для работы с классом 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 в текстовом редакторе.

Первые 10 символов

Первые 10 символов

Можно было считать все байты, тогда всё содержимое первого файла копировалось во второй. Для полного считывания строку

QByteArray block = fileIn.read(10);

Нужно заменить на строку

QByteArray block = fileIn.readAll();

В результате программа считает все байты в массив block, а после запишет их во второй файл.

Мы можем записывать информацию в файл строками, для этого его нужно открыть в текстовом режиме.

fileOut.open(QIODevice::WriteOnly | QIODevice::Text);

После передать адрес в конструктор нового объекста класса QTextStream.

QTextStream writeStream(&fileOut);

Пример программы, в которая записывает в файл fileout.txt строку «Text, text, text.»

#include #include // Подключаем класс QFile #include // Подключаем класс 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 return a.exec(); >

Содержимое fileout.txt после запуска программы

Содержимое файла fileout.txt

Содержимое файла fileout.txt

Запись в конец файла

Предыдущий метод полностью перезаписывал данные в файле, то есть очищал всё его содержимое и записывал новые данные. Перезаписи можно избежать и записывать новые данные в конец файла.

Флаг QIODevice::Append помещает указатель для записи (seek) в конец файла, в итоге входящий поток записывается сразу после имеющейся информации в файле. Пример фрагмента использования:

fileOut.open(QIODevice::Append | QIODevice::Text);

В примере вместо QIODevice::WriteOnly используется QIODevice::Append. Если сделать такое изменение в предыдущей программе, то после нескольких запусков в файле fileout.txt будет храниться строчка

Text, text, text.Text, text, text.Text, text, text.

Итак, мы рассмотрели основные методы для работы с файлами. Более подробную информацию обо всех методах класса QFile и QIODevice можно найти в официальной документации Qt и в сети.

Для вас это может быть интересно:

QFile и файлы. Чтение и запись строк в файл. : 4 комментария

  1. Sandman19 26.09.2015 Помогло разобраться с классом, хорошо изложено! ��

Qt коддинг

Это будет первый из нескольких способов чтения данных из файлов. Я постараюсь постепенно усложнять процесс чтения, но при этом будет повышаться эффективность для конкретных задач.

Создадим стандартное Gui приложение Qt с названием fileReading.
На выходе получим 5 файлов:
fileReading.pro — файл проекта;
mainwindow.h — заголовочный файл главного окна;
mainwindow.cpp — файл исходных кодов главного окна;
main.cpp — main.cpp :);
mainwindow.ui — файл формы главного окна.

Итак, в файле mainwindow.h подключаем QFile для работы с файлами и QDebug дабы выводить считанную информацию в консоль.

#include
#include

Также нам потребуется QByteArray , который нам будет возвращать класс QFile .

#include

Ну и конечно же класс строки, без которого не обходится ни одна GUI программа.

#include

В этом же файле объявим функцию для чтения из файла:

public:
void readFile();

Теперь переходим в mainwindow.cpp. В этом файле определим нашу функцию.

void MainWindow::readFile()
QFile file("file.txt"); // создаем объект класса QFile
QByteArray data; // Создаем объект класса QByteArray, куда мы будем считывать данные
if (!file.open(QIODevice::ReadOnly)) // Проверяем, возможно ли открыть наш файл для чтения
return; // если это сделать невозможно, то завершаем функцию
data = file.readAll(); //считываем все данные с файла в объект data
qDebug() QString(data); // Выводим данные в консоль, предварительно создав строку из полученных данных

В конструкторе file указывается имя файла, либо полный путь до файла, который необходимо считать, так что предварительно вам будет необходимо его создать.
Надеюсь закомментировал все наглядно.

10 комментариев:

Да, очень хорошо. Спасибо! Ответить Удалить

Да не за что ) Ответить Удалить

мда.. времени, конечно, прошло порядочно, но, может, подскажете?
как реализовать средствами Qt чтение без буфера? нужен аналог вот такого кода:
< FILE *f = fopen(str,"r");
setbuf(f,NULL); >
А Qt, как я понимаю, по-умолчанию буфер включает — как отключить -не могу найти. ( Ответить Удалить

Не совсем понимаю что вы хотите от кода.
Возможно вам поможет QDataStream? Ответить Удалить

Спасибо, очень помогло. Но к сожалению не читает кирилические символы. Вы знаете как исправить? Ответить Удалить

Этот комментарий был удален автором. Ответить Удалить

Не могу прочесть байты

#include [QFile]// все как положено (здесь угловые скобки не позволяют сорри)
#include [QByteArray]// ага.
.
public:
explicit
.
int n;// еще вот эту переменную объявим

QFile file(«d:\\file.txt»);/* выбрали файл, переменая «file» теперь за все отвечает. да два слеша обязательно!)) */
QByteArray n file.read(1);/* читаем в переменную n по одному байту — (1)*/

и вот далее я не могу эту «n» использовать, пусто. Берет как Hex как Char, но не как Int, даже Byte такого типа не нашел (чтобы n.fromByte();)
__________________________

В общем, сам отыскал =) вдруг кому приргодится

Создаем еще строковую, текстовую переменную (там, в «explicit», mainwindow.h)
QString s;

теперь идем в mainwindow.cpp и пишем

QByteArray str = file.read(1).toHex();/* прочитали байт как Hex-число в строку */
n = str.toInt();/* преобразовали его в байт, в целое число. ну, был байт 13, а в хэксе он 0D и вот она из 0D опять в 13 перевела, жаль, что сразу нельзя 13 получить в Int!*/

теперь n можно анализировать (если обрабатываете бинарный, не текстовый файл), а я искал в файлах байты перевода строки #0D, #0A, которые читая файл как текст не обнаружишь. Ответить Удалить

Еще остался без ответа пост «Но к сожалению не читает кирилические символы.»
Тут есть особенность. Текстовый файл может быть не в режиме cp1251, или там koi-8, а в юникоде, т.е. UTF8. Это значит, что теперь все нац.символы кодируются в два байта. Скажем, раньше за русскую букву «ю» отвечал байт 209, а теперь будут отвечать 209 и 142 и читать их следует парой). Если прочесть по-байтно, то первый символ будет считаться управляющим и в тексте его программа не разместит. Либо выскочит абракадабра, либо вопросики, или вообще ничего. Но тут еще препятствие — BOM.
Надо прочитать начало текстового файла и выяснить наличие этого BOM, оy сообщает, что сейчас символы пойдут парами, хотя есть UTF8 и без bom.
Вообще, чтобы так уж не «запариваться», лучше прочесть все в текстовую переменную (если файл небольшой) иkb выполнить что-то вроде:

QTextStream in(&inFile);// откуда читаем
QTextStream out(&outFile);// куда записываем
out.setCodec(«UTF-8»);// пишем в юникод

а для текстовых переменных:
string1 = «. кусок текста в кодировке UTF8»
string2 = string1.fromUTF8();// но string2 должна быть cp1251, т.е. не UTF8
/* или */
string2 = QString::fromUtf8(string1); Ответить Удалить

4.3. Загрузка и сохранение.

Теперь перейдем к реализации загрузки и сохранения файлов (в двоичном формате), создаваемых нашей программой. Делать мы это будем с помощью QFile и QDataStream, которые предоставляют платформо-независимый интерфейс для операций ввода/вывода двоичных данных.

Начнем с функции записи файла на диск:

bool Spreadsheet::writeFile(const QString &fileName) < QFile file(fileName); if (!file.open(IO_WriteOnly)) < QMessageBox::warning(this, tr("Spreadsheet"), tr("Cannot write file %1:\n%2.") .arg(file.name()) .arg(file.errorString())); return false; >QDataStream out(&file); out.setVersion(5); out > QApplication::restoreOverrideCursor(); return true; >

Функция writeFile() вызывается из MainWindow::saveFile(), для записи файла на диск. В случае успеха возвращает true, иначе — false.

Функция начинается с создания экземпляра QFile, с заданным именем файла, после чего файл открывается на запись. Затем создается объект QDataStream, который, используя QFile, записывает данные на диск. Непосредственно перед записью данных, мы меняем внешний вид курсора мыши, показывая занятость приложения. А после записи — восстанавливаем его. В конце функции файл автоматически закрывается деструктором QFile.

QDataStream поддерживает основные типы языка C++, а так же ряд типов, определяемых библиотекой Qt. Синтаксис соответствует стандарту классов . Например,

записывает переменные x, y и z в поток, а

in >> x >> y >> z;

читает их из потока.

Поскольку базовые типы языка C++ char, short, int, long и long long могут иметь различный размер на разных платформах, в целях безопасности их следует приводить к одному из следующих: Q_INT8, Q_UINT8, Q_INT16, Q_UINT16, Q_INT32, Q_UINT32, Q_INT64, Q_UINT64, которые гарантированно имеют декларируемый, в битах, размер.

QDataStream -- довольно универсальный класс, он может совместно работать не только с QFile, но так же и с QBuffer, и с QSocket, и с QSocketDevice. Точно так же QFile может использоваться совместно с QTextStream и как самостоятельное средство работы с файлами. В Главе 10 мы глубже рассмотрим эти классы.

Формат файлов приложения Spreadsheet очень прост. Начинается файл с 32-х битного числа, идентифицирующего формат (MagicNumber определена как 0x7F51C882 в spreadsheet.h). Далее следует серия блоков, каждый из которых соответствует одной ячейке (номера строки и колонки, и формула). Для экономии мы не записываем в файл пустые ячейки.

Рисунок 4.5. Формат файла Spreadsheet.

Двоичное представление типов данных определяется классом QDataStream. Например, тип Q_UINT16 представлен двумя байтами, следующими в порядке big-endian (т.е. первым идет старший байт, потом -- младший). Тип QString записывается как последовательность символов в кодировке Unicode.

Двоичное представление типов, определяемых библиотекой Qt, стало осуществляться еще в Qt 1.0 и, вероятно, будет развиваться и дальше, чтобы в процессе развития библиотеки имелась возможность представлять в двоичном виде вновь появляющиеся типы. По-умолчанию, QDataStream использует самую современную версию двоичного формата (версия 5 в Qt 3.2), но способен работать и с более ранними версиями. Воизбежание проблем с совместимостью, на тот случай, если наша программа будет скомпилирована с более свежим выпуском Qt, мы укажем QDataStream на то, что необходимо использовать 5-ю версию, независимо от того, с какой версией Qt была скомпилирована программа.

bool Spreadsheet::readFile(const QString &fileName) < QFile file(fileName); if (!file.open(IO_ReadOnly)) < QMessageBox::warning(this, tr("Spreadsheet"), tr("Cannot read file %1:\n%2.") .arg(file.name()) .arg(file.errorString())); return false; >QDataStream in(&file); in.setVersion(5); Q_UINT32 magic; in >> magic; if (magic != MagicNumber) < QMessageBox::warning(this, tr("Spreadsheet"), tr("The file is not a " "Spreadsheet file.")); return false; >clear(); Q_UINT16 row; Q_UINT16 col; QString str; QApplication::setOverrideCursor(waitCursor); while (!in.atEnd()) < in >> row >> col >> str; setFormula(row, col, str); > QApplication::restoreOverrideCursor(); return true; >

Функция readFile() очень похожа на writeFile(). Для работы с файлом опять используется QFile, только на этот раз при открытии файла устанавливается флаг режима доступа IO_WriteOnly. Далее идет установка версии формата. При чтении данных в двоичном представлении всегда должна указываться та же версия, которая использовалась при записи.

Если сигнатура файла (magic number) представлена корректным значением, то вызывается clear(), для очистки таблицы, поскольку в файле могут быть представлены не все ячейки.

Пред. В начало След.
Создание класса-потомка от QTable. На уровень выше Реализация меню Edit.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *