Каков наилучший способ чтения / записи объектов в файле при следующих условиях - PullRequest
0 голосов
/ 11 февраля 2020

Я готов хранить объекты в базе данных. Цель состоит в том, чтобы иметь возможность читать / записывать эти объекты с помощью программы. Требования следующие:

  • Объекты могут быть сложными с использованием классов Qt, таких как QList, QString ... или даже могут содержать другие объекты, использующие QObjects
  • База данных не должна читаться или изменяться человеком (без текстового файла, и если я использую базу данных sqlite, она должна быть зашифрована каким-либо образом)
  • Я должен иметь возможность удалить, прочитать объект по его имени и подсчитать количество объектов в базе данных, не загружая все в память

Я задал вопрос здесь , чтобы сделать это с QDataStream с минималистским примером. Но, похоже, это не лучший способ продолжить. Не могли бы вы дать какие-нибудь предложения относительно решений, которые существуют для этой цели?

Я пробовал следующее, но оно не удовлетворяет требованиям:

  • Хранение текста в sqlite с помощью QtSQL: но данные доступны, например, с помощью sqlitemanager, могут быть изменены или удалены людьми. Более того, я понятия не имею, как хранить QList, например, или другие созданные мной объекты и содержать QObject (например, 2 QList)
  • Хранение двоичных данных с использованием QDataStream: в этом случае я не могу подсчитать количество объектов в моем файле, ни прочитать, ни удалить указанный объект c без загрузки всего файла в память.

Я бы будьте благодарны, если вы могли бы дать мне несколько предложений или привести пример, даже если этот пример минималистский.

1 Ответ

0 голосов
/ 13 февраля 2020

Я наконец-то нашел решение, особенно благодаря Игорю Тандетнику и благодаря топи c здесь

Я не совсем завершил, есть небольшое несовершенство, потому что у меня есть определить объект моего пользовательского класса, который я не использую для вызова функции readFromDB для генерации моего объекта из БД.

С другой стороны, я получаю это сообщение об ошибке "QSqlDatabasePrivate :: addDatabase : дублирующее имя соединения 'qt_sql_default_connection', старое соединение удаляется "каждый раз, когда я вызываю свою базу данных.

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

Еще раз спасибо.

#include "QString"
#include "QFile"
#include "QDataStream"
#include "qdebug.h"
#include "QtSql"
#include "QSqlDatabase"
#include "qmessagebox.h"

class User
{
protected:
QString name;
QList<QString> childrens;

public:
QString getName(){ return name;}
QList<QString> getChildrens(){ return childrens;}

void setName(QString x) {name = x;}
void setChildrens(QList<QString> x) {childrens = x;}



friend QDataStream &operator<<(QDataStream &out, const User &t)
{
    out << t.name << t.childrens;
    return out;
}

friend QDataStream &operator>>(QDataStream &in, User &t)
{
    QString inname;
    QList<QString> inchildrens;
    in >> inname >> inchildrens;
    t.name = inname;
    t.childrens = inchildrens;
    return in;
}
QByteArray object2blob( const User& user )
{
  QByteArray result;
  QDataStream bWrite( &result, QIODevice::WriteOnly );
  bWrite << user;

  return result;

}
User blob2object( const QByteArray& buffer )
{
  User result;
  QDataStream bRead( buffer );
  bRead >> result;

  return result;
}
int saveToDB( const User& user )
{
    QSqlDatabase myDB = QSqlDatabase::addDatabase("QSQLITE");
    myDB.setDatabaseName( "file.db");
    if (!myDB.open())
    {
        qDebug()<<"Failed to open SQL database of registered users";
    }
    else
    {
        qDebug()<<"Successfully opening SQL database of registered users";
        QSqlQuery query;

        query.prepare( "CREATE TABLE IF NOT EXISTS users (name TEXT, childrens BLOB)" );
          if( !query.exec() )
          {
            qDebug() << query.lastError();
          }
          else
          {
            qDebug() << "Table created!";
            query.prepare( "INSERT INTO users (name,childrens) VALUES (:name,:childrens)" );
            query.bindValue(":name", name);
            query.bindValue( ":childrens",  object2blob(user) );
            query.exec();
          }
        query.clear();
        myDB.close();
    }
    QSqlDatabase::removeDatabase("UserConnection");

    return 0;
}
User readFromDB( QString name )
{
    User result;
    QSqlDatabase myDB = QSqlDatabase::addDatabase("QSQLITE");
    myDB.setDatabaseName( "file.db");
    if (!myDB.open())
    {
        qDebug()<<"Failed to open SQL database of registered users";
    }
    else
    {
        QSqlQuery query;

        query.prepare( "SELECT * FROM users WHERE name ='"+ name +"'" );
        //query.bindValue( 0, name );

        if ( query.exec() && query.next() ) {
          result = blob2object( query.value( 1 ).toByteArray() );
        }
        query.clear();
        myDB.close();
    }
    QSqlDatabase::removeDatabase("UserConnection");
    qDebug()<<result.getChildrens();
    return result;
}
};


////////////////////////////////////////////////////////////////
int main()
{
    User u;
    u.setName("Georges");
    u.setChildrens(QList<QString>()<<"Jeanne"<<"Jean");
    u.saveToDB(u);

    User v;
    v.setName("Alex");
    v.setChildrens(QList<QString>()<<"Matthew");
    v.saveToDB(v);

    User w;
    w.setName("Mario");
    w.saveToDB(w);

    User to_read; //to improve here
    User a = to_read.readFromDB("Georges");

    qDebug()<<a.getChildrens();
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...