简体   繁体   English

你如何序列化QMap?

[英]How do you serialize a QMap?

I'm trying to learn how to serialize QMap objects in windowed applications, using this code: 我正在尝试使用以下代码学习如何在窗口化应用程序中序列化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
}

The write() function called by btnSave does indeed save the QMap. btnSave调用的write()函数确实保存了QMap。 I can see the data in snippets.txt. 我可以在snippets.txt中看到数据。 I can see in the debugger that the read() function, however, doesn't assign anything to the map variable. 我可以在调试器中看到, read()函数并未将任何内容分配给map变量。 What am I missing? 我错过了什么?

The proper QMap serialization and deserialization code is the following: 正确的QMap序列化和反序列化代码如下:

main.cpp 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;
}

main.pro main.pro

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

Build and Run 构建并运行

qmake && make && ./main

Output 产量

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

You have had several issues: 您遇到了几个问题:

This made it really difficult for you to reveal the real issues. 这使您很难揭示真正的问题。

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 ia 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: 通过QDataStream进行QDataStream ,它有点隐蔽,但是如果直接通过QFile实例阅读时快速浏览QIODevice文档 ,则会更加清楚错误打开模式的底层内容

Reads at most maxSize bytes from the device into data, and returns the number of bytes read. 从设备读取最多maxSize字节为数据,并返回读取的字节数。 If an error occurs, such as when attempting to read from a device opened in WriteOnly mode, this function returns -1. 如果发生错误(例如,当尝试从以WriteOnly模式打开的设备中读取数据时),此函数将返回-1。

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. 在这种情况下,您应该使用类似重新搜索开头和QIODevice :: ReadWrite的方法。 Having said that, it is just another way of doing it. 话虽如此,这只是另一种方式。

  • Incorrect use of qDebug() qDebug()的使用不正确

This is just a side note, but you were adding spaces explicitly, whereas qDebug() is already doing that for you. 这只是一个附注,但你明确地添加了空格,而qDebug()已经为你做了。

  • Needless flushing of the file when serializing. 序列化时不必要地刷新文件。

This is superfluous as it is automatically done when closing the file descriptor through the class destructor. 这是多余的,因为通过类析构函数关闭文件描述符时,它是自动完成的。

  • Needless closure of the file object 不必要地关闭文件对象

This is automatically done by proper RAII. 这是由适当的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. 由于您保留了函数的作用域,因此在堆栈上构造析构函数时,将自动为文件对象调用析构函数。

May be that's because you are opening the file as WriteOnly in your read function. 可能是因为您在读取功能中以WriteOnly打开文件。 The correct form is: 正确的形式是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM