简体   繁体   中英

How do you serialize a 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
}

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?

The proper QMap serialization and deserialization code is the following:

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

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:

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.

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.

  • Incorrect use of qDebug()

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

  • 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. 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. The correct form is:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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