How do you serialize QMap?

I am 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 actually saves the QMap. I can see the data in snippets.txt. In the debugger, I see that the read() function does not assign anything to the map variable. What am I missing?

+2
source share
2 answers

The native QMap serialization and deserialization code is as follows:

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 

Assembly and launch

 qmake && make && ./main 

Exit

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

You had a few problems:

This made it difficult for you to solve real problems.

This was a problem hidden from you, without proper reporting of errors. The problem here is that when opening a file for writing only, any subsequent read operation will give a natural result. This will be a little QDataStream when executing QDataStream , but if you quickly look through the QIODevice documentation when you read directly through the QFile instance it becomes a little more clear what happens under the wrong open mode:

Reads in most bytes maxSize from the device to the data and returns the number of bytes read. If an error occurs, for example, when trying to read from a device that is open in WriteOnly mode, this function returns -1.

If you checked the errors, that would be clearer. In fairness, it follows that in your case, sharing a file without closing it before operations can be acceptable in this simple snippet. In this case, you would use something like re-search at the beginning and QIODevice :: ReadWrite. Having said that, this is just another way to do it.

  • Misuse of qDebug ()

This is just a side note, but you explicitly added spaces, while qDebug () already does this for you.

  • Optional file cleanup during serialization.

This is superfluous, since it is automatically executed when the file descriptor is closed through the class destructor.

  • Incorrect file object closure

This is automatically done using the correct RAII. Desctructor will close it for you if the file is still open. As you leave the scope of the function, the destructor will be called automatically for your file object as it is created on the stack.

+6
source

Maybe because you open the file as WriteOnly in your read function. The correct form:

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

Source: https://habr.com/ru/post/1013361/


All Articles