首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何序列化QMap?

如何序列化QMap?
EN

Stack Overflow用户
提问于 2014-12-04 03:42:16
回答 2查看 4.6K关注 0票数 2

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

代码语言:javascript
复制
#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
}

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-04 04:29:51

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

main.cpp

代码语言:javascript
复制
#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

代码语言:javascript
复制
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp

构建和运行

代码语言:javascript
复制
qmake && make && ./main

输出

代码语言:javascript
复制
QMap(("one", "this is 1")("three", "this is 3")("two", "this is 2"))

你们有几个问题:

  • 完全忽略错误码和字符串

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

  • 打开阅读时使用QIODevice::只写

这是在没有正确的错误报告的情况下向您隐藏的问题。这里的问题是,当您打开仅用于写入的文件时,任何后续的读取操作都将自然产生空结果。在通过QDataStream进行此操作时,它有点隐藏,但如果您在直接读取QFile实例时快速查看QIODevice文档,就会更加清楚地了解在下面发生了哪些错误的开放模式:

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

如果您检查了错误,这将变得更清楚。公平地说,在您的示例中,在这个简单的代码段中,在操作之前共享文件而不关闭文件是可以接受的。在这种情况下,您可能会使用类似于“重新寻找开始”和“QIODevice::ReadW区”之类的东西。话虽如此,但这只是另一种做法。

  • 不正确使用qDebug()

这只是附带的注意事项,但是您是显式地添加空格,而qDebug()已经为您添加了空格。

  • 序列化时对文件进行不必要的刷新。

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

  • 不必要地关闭文件对象

这是由适当的RAII自动完成的。如果文件还没打开,卡车司机会帮你关闭的。由于您保留了函数的作用域,在堆栈上构造文件对象时,析构函数将被自动调用。

票数 9
EN

Stack Overflow用户

发布于 2014-12-04 04:19:08

这可能是因为您在读取函数中以WriteOnly的形式打开文件。正确的表格是:

代码语言:javascript
复制
if (!myFile.open(QIODevice::ReadOnly))
{
    qDebug() << "Could not read " << filename;
    return (map);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27285889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档