你如何序列化QMap?

Al *_*l C 2 c++ qt qmap qfile qtcore

我正在尝试使用以下代码学习如何在窗口化应用程序中序列化QMap对象:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QString>
#include <QDataStream>
#include <QMap>
#include <QDebug>


void write ()
{
   QString filename = "Z:/snippets.txt";
   QFile myFile (filename);

   if (!myFile.open(QIODevice::WriteOnly))
   {
       qDebug() << "Could not write " << filename;
       return;
   }

   QMap<QString,QString> map;
   map.insert("one","this is 1");
   map.insert("two","this is 2");
   map.insert("three","this is 3");

   QDataStream out (&myFile);
   out.setVersion(QDataStream::Qt_5_3);
   out<<map;

   myFile.flush();
   myFile.close();
}

QMap<QString,QString> read ()
{
    QString filename = "Z:/snippets.txt";
    QFile myFile (filename);
    QMap<QString,QString> map;
    QDataStream in (&myFile);
    in.setVersion(QDataStream::Qt_5_3);

    if (!myFile.open(QIODevice::WriteOnly))
    {
        qDebug() << "Could not read " << filename;
        return (map);
    }

    in >> map;

    myFile.close();
    return(map);
}

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

}

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

void MainWindow::on_btnSave_clicked()
{
    write();
}

void MainWindow::on_btnLoad_clicked()
{
    QMap<QString,QString> map;
    map = read();
    QMapIterator<QString,QString> i(map);
    //do other stuff
}
Run Code Online (Sandbox Code Playgroud)

write()btnSave调用的函数确实保存了QMap.我可以在snippets.txt中看到数据.我可以在调试器中看到该read()函数没有为map变量赋值.我错过了什么?

lpa*_*app 7

正确的QMap序列化和反序列化代码如下:

main.cpp中

#include <QString>
#include <QFile>
#include <QMap>
#include <QDataStream>
#include <QDebug>

void write()
{
   QString filename = "snippets.txt";
   QFile myFile(filename);
   if (!myFile.open(QIODevice::WriteOnly))
   {
       qDebug() << "Could not write to file:" << filename << "Error string:" << myFile.errorString();
       return;
   }

   QMap<QString, QString> map;
   map.insert("one", "this is 1");
   map.insert("two", "this is 2");
   map.insert("three", "this is 3");

   QDataStream out(&myFile);
   out.setVersion(QDataStream::Qt_5_3);
   out << map;
}

QMap<QString,QString> read()
{
    QString filename = "snippets.txt";
    QFile myFile(filename);
    QMap<QString, QString> map;
    QDataStream in(&myFile);
    in.setVersion(QDataStream::Qt_5_3);

    if (!myFile.open(QIODevice::ReadOnly))
    {
        qDebug() << "Could not read the file:" << filename << "Error string:" << myFile.errorString();
        return map;
    }

    in >> map;
    return map;
}

int main()
{
    write();
    qDebug() << read();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

main.pro

TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Run Code Online (Sandbox Code Playgroud)

构建并运行

qmake && make && ./main
Run Code Online (Sandbox Code Playgroud)

产量

QMap(("one", "this is 1")("three", "this is 3")("two", "this is 2"))
Run Code Online (Sandbox Code Playgroud)

你有几个问题:

这使你很难揭示真正的问题.

如果没有正确的错误报告,这是您隐藏的问题.这里的问题是当你打开文件只进行写入时,任何后续的读操作都会自然产生空结果.它在执行时有点隐藏QDataStream,但如果您在直接通过QFile实例阅读时快速查看QIODevice文档,那么对于错误的打开模式,下面会发生什么变得更加清晰:

从设备读取最多maxSize字节为数据,并返回读取的字节数.如果发生错误,例如尝试从以WriteOnly模式打开的设备读取时,此函数返回-1.

如果您检查了错误,这将变得更加清晰.公平地说,在你的情况下共享文件而不关闭它,然后在这个简单的代码片段中可以接受操作.在这种情况下,您可能会使用类似重新搜索的内容和QIODevice :: ReadWrite.话虽如此,这只是另一种方式.

  • qDebug()的使用不正确

这只是一个附注,但你明确地添加了空格,而qDebug()已经为你做了.

  • 序列化时无需刷新文件.

这是多余的,因为它是在通过类析构函数关闭文件描述符时自动完成的.

  • 无需关闭文件对象

这是由适当的RAII自动完成的.如果文件仍处于打开状态,析构函数将为您关闭它.由于您保留了函数的作用域,因此在堆栈上构造析构函数时,将自动为文件对象调用析构函数.