您如何序列化QMap? [英] How do you serialize a QMap?

查看:532
本文介绍了您如何序列化QMap?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to learn how to serialize QMap objects in windowed applications, using this code:

#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
}

由btnSave调用的write()函数确实可以保存QMap.我可以在snippets.txt中看到数据.我可以在调试器中看到read()函数,但是没有为map变量分配任何内容.我想念什么?

The write() function called by btnSave does indeed save the QMap. I can see the data in snippets.txt. I can see in the debugger that the read() function, however, doesn't assign anything to the map variable. What am I missing?

推荐答案

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

The proper QMap serialization and deserialization code is the following:

#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;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp

构建并运行

qmake && make && ./main

输出

QMap(("one", "this is 1")("three", "this is 3")("two", "this is 2"))

您遇到了几个问题:

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

This made it really difficult for you to reveal the real issues.

这是您隐藏的问题,没有正确的错误报告.这里的问题是,当您打开文件以仅进行写入时,任何后续的读取操作自然会产生空结果.通过QDataStream进行操作时,它有点隐藏,但是如果您快速浏览 QIODevice文档,当您直接阅读QFile实例时,它会更加清楚错误打开模式下的底层情况:

This was the issue hidden from you without proper error reporting. The problem here is that when you open the file for only writing, any subsequent read operation will yield empty result naturally. It i a bit hidden when doing it through QDataStream, but if you take a quick look at the QIODevice documentation when you read directly through the QFile instance it becomes a bit more clear what is going on underneath for wrong open mode:

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

Reads at most maxSize bytes from the device into data, and returns the number of bytes read. If an error occurs, such as when attempting to read from a device opened in WriteOnly mode, this function returns -1.

如果您检查了错误,这将变得更加清楚.公平地说,在您的情况下,在此简单代码段中可以接受操作之前共享文件而不关闭它.在这种情况下,您应该使用类似重新搜索开头和QIODevice :: ReadWrite的方法.话虽如此,这只是另一种方式.

If you checked the errors, this would have become more clear. To be fair, in your case sharing the file without closing it before the operations could have been acceptable in this simple snippet. In that case, you would have used something like re-seek to the beginning and QIODevice::ReadWrite. Having said that, it is just another way of doing it.

  • 不正确使用qDebug()

这只是一个附带说明,但是您正在显式添加空格,而qDebug()已经为您完成了此操作.

This is just a side note, but you were adding spaces explicitly, whereas qDebug() is already doing that for you.

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

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

This is superfluous as it is automatically done when closing the file descriptor through the class destructor.

  • 无需关闭文件对象

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

This is automatically done by proper RAII. The desctructor will close it for you if the file is still open. Since you leave the scope of the function, the destructor will be called automatically for your file object as it is constructed on the stack.

这篇关于您如何序列化QMap?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆