Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

Ниже показано, как можно сохранить целый тип QImage и QMap<QString, QColor> в файле с именем facts.dat:

QImage image("philip.png");

QMap<QString, QColor> map;

map.insert("red", Qt::red);

map.insert("green", Qt::green);

map.insert("blue", Qt::blue);

QFile file("facts.dat");

if (!file.open(QIODevice::WriteOnly)) {

cerr << "Cannot open file for writing: "

<< qPrintable(file.errorString) << endl;

return;

}

QDataStream out(&file);

out.setVersion(QDataStream::Qt_4_1);

out << quint32(0x12345678) << image << map;

Если

не удается открыть файл, мы информируем об этом пользователя и возвращаем управление. Макрос qPrintable возвращает const char *, принимая QString. (Можно было бы поступить по-другому и использовать функцию QString::toStdString, возвращающую тип std::string, для которого в <iostream> предусмотрена соответствующая перегрузка оператора <<.)

При успешном открытии файла мы создаем QDataStream и определяем его номер версии. Номер версии — это целое число, влияющее на представление в Qt типов данных (базовые типы данных С++ всегда представляются одинаково). В Qt 4.1 большинство сложных форматов имеют версию 7. Мы можем либо жестко закодировать в программе константу 7, либо использовать символическое имя QDataStream::Qt_4_1.

Чтобы обеспечить представление значения 0x12345678 в виде 32-битового целого числа без знака на всех платформах, мы приводим его тип к quint32 — типу данных, размер которого всегда равен точно 32 битам. Для обеспечения функциональной совместимости QDataStream по умолчанию использует прямой порядок байтов (big-endian); это можно изменить, вызывая функцию setByteOrder.

Нам не надо явно закрывать файл, поскольку это делается автоматически, когда переменная типа QFile выходит из области видимости. Если необходимо убедиться в том, что данные действительно записаны, мы можем вызвать функцию flush и проверить возвращаемое значение (true при успешном завершении).

Программный код для чтения данных является зеркальным отражением кода, используемого нами для записи данных:

quint32 n;

QImage image;

QMap<QString, QColor> map;

QFile file("facts.dat");

if (!file.open(QIODevice::ReadOnly)) {

cerr << "Cannot open file for reading: "

<< qPrintable(file.errorString) << endl;

return;

}

QDataStream in(&file);

in.setVersion(QDataStream::Qt_4_1);

in >> n >> image >> map;

При чтении используется та же самая версия QDataStream, которую мы использовали при записи. Это условие должно выполняться всегда. Жестко кодируя номер версии, мы гарантируем успешное чтение и запись данных приложением (при условии компиляции приложения с версией Qt 4.1

или более поздней версией Qt).

QDataStream так хранит данные, что мы сможем их считать обратно без особых усилий. Например, QByteArray представляется в виде структуры с 32-битовым счетчиком байтов, за которым идут сами байты. Используя функции readRawBytes и writeRawBytes, QDataStream может также применяться для чтения и записи неформатированных байтов, не имеющих заголовка в виде счетчика байтов.

Обрабатывать ошибки при чтении данных из потока QDataStream достаточно просто. Этот поток данных имеет функцию status, возвращающую значения QDataStream::Ok, QDataStream::ReadPastEnd или QDataStream::ReadCorruptData. При возникновении ошибки оператор >> всегда считывает нулевые или пустые значения. Это означает, что во многих случаях можно просто считывать файл целиком, не беспокоясь о возможных ошибках, и в конце удостовериться в успешном выполнении чтения, проверив получаемое функцией status значение.

QDataStream работает с разнообразными типами данных С++ и Qt; полный их список доступен в сети Интернет по адресуКроме того, можно добавить поддержку своих собственных пользовательских типов, перегружая операторы << и >>. Ниже приводится определение пользовательского типа данных, которое может быть использовано совместно с QDataStream:

01 class Painting

02 {

03 public:

04 Painting { myYear = 0; }

05 Painting(const QString &title, const QString &artist, int year) {

06 myTitle = title;

07 myArtist = artist;

08 myYear = year;

09 }

10 void setTitle(const QString &title) { myTitle = title; }

11 QString title const { return myTitle; }

12 …

13 private:

14 QString myTitle;

15 QString myArtist;

16 int myYear;

17 };

18 QDataStream &operator << (QDataStream &out, const Painting &painting);

19 QDataStream &operator >> (QDataStream &in, Painting &painting);

Ниже показана возможная реализация оператора <<:

01 QDataStream &operator << (QDataStream &out, const Painting &painting)

02 {

03 out << painting.title << painting.artist

04 << quint32(painting.year);

05 return out;

06 }

Для вывода Painting мы просто выводим две строки типа QString и значение типа quint32. В конце функции мы возвращаем поток. Этот обычный в С++ прием позволяет использовать последовательность операторов << для вывода данных в поток. Например:

Поделиться с друзьями: