IT Notes

Сохранение данных в файл средствами Qt

Не в каждом приложении требуется использовать базы данных. Во многих случаях предпочтительнее оказываются простые файлы. Сохранять и считывать текстовую информацию в Qt можно с помощью QTextStream, а для бинарных данных существует QDataStream. Рассмотрим примеры их использования.

QTextStream: Сохранение текста

Работа с текстовыми файлами в Qt осуществляется следующим образом:

#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QTextCodec>

int main() {
    QTextCodec::setCodecForLocale( QTextCodec::codecForName( "UTF-8" ) );

    static const char* const FILE_NAME = "test.txt";
    QFile out( FILE_NAME );
    if( out.open( QIODevice::WriteOnly ) ) {
        QTextStream stream( &out );
        stream << QObject::trUtf8( "Проверка!" );
        out.close();
    }

    QFile in( FILE_NAME );
    if( in.open( QIODevice::ReadOnly ) ) {
        QTextStream stream( &in );
        qDebug() << stream.readAll();
        in.close();
    }

    return 0;
}

В приведенном примере сначала осуществляется сохранение строки "Проверка!" в файл с именем test.txt. Затем тот же файл открывается для чтения, и его содержимое выводится на экран консоли.

Полное оздоровление при неизлечимом, гормональном.

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

out.open( QIODevice::Append );

Обратите внимание на строку:

QTextCodec::setCodecForLocale( QTextCodec::codecForName( "UTF-8" ) );

Она нужна, чтобы обеспечить поддержку символов юникода в операциях чтения/записи. В зависимости от платформы и конфигурации системы, это может и не понадобится. Однако если по умолчанию используется не-кириллическая кодировка, то вместо текста "Проверка!" в файл может записаться что угодно. Например, останется только восклицательный знак, а все русские символы пропадут. То же самое относится и к выводу кириллических символов на консоль с помощью QDebug.

Кодировку для QTextStream можно установить отдельно:

QTextStream stream( &out );
stream.setCodec( "UTF-8 ");

QDataStream: Сохранение бинарных данных

Использование QDataStream мало чем отличается от QTextStream:

#include <QFile>
#include <QDataStream>
#include <QDebug>
#include <QTextCodec>

int main() {
    QTextCodec::setCodecForLocale( QTextCodec::codecForName( "UTF-8" ) );

    static const char* const FILE_NAME = "test.bin";
    QFile out( FILE_NAME );
    if( out.open( QIODevice::WriteOnly ) ) {
        QDataStream stream( &out );
        stream << QObject::trUtf8( "Проверка!" );
        out.close();
    }

    QFile in( FILE_NAME );
    if( in.open( QIODevice::ReadOnly ) ) {
        QString str;
        QDataStream stream( &in );
        stream >> str;
        qDebug() << str;
        in.close();
    }

    return 0;
}

Основное преимущество использования бинарного формата заключается в компактности хранимых данных. Однако имеется и множество недостатков:

  1. Нечитаемость содержимого, которое очень трудно (практически невозможно) просматривать и редактировать в текстовом редакторе;
  2. Зависимость от версии Qt, поскольку реализация QDataStream может немного меняться;
  3. Сложность сопровождения в случае изменения структуры хранимых данных. Если у класса, который сохраняется в бинарном виде, добавляются новые поля, то возникает проблема совместимости с файлами, созданными ранее.

Подробности использования QDataStream смотрите в заметке о сериализации данных в Qt.

Похожие публикации

Комментарии

static const char* const FILE_NAME = "test.bin"; - это зачем вообще?

QString использовать религия не позволяет?

И зачем вообще static?

Объясните дураку!

Здравствуйте

alex_rage:

static const char* const FILE_NAME = "test.bin"; - это зачем вообще?

QString использовать религия не позволяет?

Особой функциональной разницы между const char* const и QString в рассматриваемом случае нет. Это дело вкуса

alex_rage:

И зачем вообще static?

А static const - привычка. Обычно хуже от этого не бывает, но в зависимости от компилятора код может оказаться более оптимальным. Конечно, внутри main() это каких-либо преимуществ не дает