5

我将在二进制文件中保存一个结构并稍后加载它。我发现一种方法是使用QVariant. 这是我创建的一个简化的Qt Widget 应用程序示例。但是当我运行它时,二进制文件仍然是空的。你能帮我解决这个问题吗?另外,有没有更好的方法来做这样的事情?

主窗口.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QFileDialog>
#include <QDataStream>
#include <QString>

#include "mystruct.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};
#endif

主窗口.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /* create an object of the struct */
    myStruct * aStruct = new myStruct;
    aStruct->myStringVar = QString("aaaaa");

    /* put the object in QVariant */
    QVariant aVariant;
    aVariant.setValue(aStruct);

    /* save the QVariant to binary file */
    QFile myFile("myFile");
    QDataStream save(&myFile);
    save.setVersion(QDataStream::Qt_4_6);
    save << aVariant;
    myFile.close();

    /* load the QVariant from binary file */
    QDataStream load(&myFile);
    load.setVersion(QDataStream::Qt_4_6);
    QVariant theVariant;
    load >> theVariant;
    QString theVar = theVariant.value<myStruct*>()->myStringVar;
    myFile.close();
}

MainWindow::~MainWindow()
{
    delete ui;
}

mystruct.h:

#ifndef MYSTRUCT_H
#define MYSTRUCT_H

#include <QMetaType>
#include <QString>

struct myStruct
{
    QString myStringVar;
};

Q_DECLARE_METATYPE(myStruct*)

#endif // MYSTRUCT_H

评论:作为参考,此链接显示了类似的问题,但我无法正确理解/实施建议。例如,我试图定义一个新的运算符,正如这里所解释的那样但它不起作用。

4

2 回答 2

9

首先你不应该保存指针,因为这只是变量的内存地址,应该保存的是值。另一方面,如果要使用 QDataStream,则必须覆盖流运算符,最后,如果要保存为 QVariant,则必须使用 qRegisterMetaTypeStreamOperators。除了上述之外,您的代码还有几个错误,例如没有打开 QFile。

mystruct.h

#ifndef MYSTRUCT_H
#define MYSTRUCT_H

#include <QString>
#include <QMetaType>

struct myStruct
{
    QString myStringVar;
    bool operator==(const myStruct & o){
        return o.myStringVar == this->myStringVar;
    }
    friend QDataStream &operator<<(QDataStream &out, const myStruct &rhs){
        out << rhs.myStringVar;
        return out;
    }
    friend QDataStream &operator>>(QDataStream &in, myStruct &rhs){
        in >> rhs.myStringVar;
        return in;
    }
};
Q_DECLARE_METATYPE(myStruct)

#endif // MYSTRUCT_H

主文件

#include "mystruct.h"

#include <QDataStream>
#include <QFile>
#include <QVariant>

int main(int argc, char *argv[])
{
    qRegisterMetaTypeStreamOperators<myStruct>("myStruct");

    // create struct
    myStruct aStructIn{"aaa"};

    // myStruct to QVariant
    QVariant aVariant;
    aVariant.setValue(aStructIn);

    //open file
    QFile myFile("myFile");
    if(!myFile.open(QIODevice::WriteOnly))
        return -1;

    // save QVariant
    QDataStream save(&myFile);
    save.setVersion(QDataStream::Qt_4_6);
    save << aVariant;
    myFile.close();

    //open file
    if(!myFile.open(QIODevice::ReadOnly))
        return -1;

    // read QVariant
    QDataStream load(&myFile);
    load.setVersion(QDataStream::Qt_4_6);
    QVariant theVariant;
    load >> theVariant;
    myFile.close();

    // QVariant to myStruct
    myStruct aStructOut = theVariant.value<myStruct>();

    Q_ASSERT(aStructOut == aStructIn);

    return 0;
}
于 2018-09-13T04:24:29.197 回答
2

这是完成所有更正后对我有用的示例。这个例子展示了我struct如何class使用QDataStream. 该结构,即myStruct,具有三个成员: an int、 astring和 a struct,即mySubStruct

  • 对于每个struct/ class,需要重载<<and运算符。>>
  • 在每个重载运算符中,结构的保存/加载是通过将结构分解为其原始成员来完成的。原始成员是QDataStream 支持的类型

评论 1:以下示例使用将运算符重载为 a struct。要查看如何重载运算符,class请参阅此链接

评论 2: 此链接是一个完整的示例。

我的substruct.h

#ifndef MYSUBSTRUCT_H
#define MYSUBSTRUCT_H

#include <QString>
#include <QDataStream>

struct mySubStruct
{
    int intVar;
    QString strVar;

    /* overload the operators */
    friend QDataStream &operator<< (QDataStream &out, const mySubStruct &rhs)
    {
        out << rhs.intVar << rhs.strVar;
        return out;
    }

    friend QDataStream &operator>> (QDataStream &in, mySubStruct &rhs)
    {
        in >> rhs.intVar >> rhs.strVar;
        return in;
    }
};
#endif // MYSUBSTRUCT_H

mystruct.h

#ifndef MYSTRUCT_H
#define MYSTRUCT_H

#include <QString>
#include <QDataStream>
#include "mysubstruct.h"

struct myStruct
{
    int intVar;
    QString strVar;
    mySubStruct subStructObj;

    /* overload the operators */
    friend QDataStream &operator<< (QDataStream &out, const myStruct &rhs)
    {
        out << rhs.intVar << rhs.strVar << rhs.subStructObj;
        return out;
    }

    friend QDataStream &operator>> (QDataStream &in, myStruct &rhs)
    {
        in >> rhs.intVar >> rhs.strVar >> rhs.subStructObj;
        return in;
    }
};
#endif // MYSTRUCT_H

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QString>
#include <QDebug>
#include "mystruct.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp显示了操作符是如何实现的。

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /* create struct */
    mySubStruct subStructIn;
    subStructIn.intVar = 1;
    subStructIn.strVar = "a";

    myStruct structIn;
    structIn.intVar = 11;
    structIn.strVar = "aa";
    structIn.subStructObj = subStructIn;

     /* open file */
     QFile myFile("myFile");

     /* save */
     if(myFile.open(QIODevice::WriteOnly))
     {
         QDataStream save(&myFile);
         save.setVersion(QDataStream::Qt_4_6);
         save << structIn;
         myFile.close();
     }

     /* load */
     myStruct structOut;
     if(myFile.open(QIODevice::ReadOnly))
     {
         QDataStream load(&myFile);
         load.setVersion(QDataStream::Qt_4_6);
         load >> structOut;
         myFile.close();
     }

     qDebug() << structOut.intVar;
     qDebug() << structOut.strVar;
     qDebug() << structOut.subStructObj.strVar;
     qDebug() << structOut.subStructObj.intVar;
}

MainWindow::~MainWindow()
{
    delete ui;
}
于 2018-09-14T15:51:17.257 回答