При успешном открытии файла мы создаем 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 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 ∈, 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 }