Qt知识点梳理 —— 自定义数据结构序列化与反序列化

article/2025/8/29 23:07:20

文章目录

定义

Qt中序列化与反序列化

序列化:

反序列化:

自定义数据结构序列化与反序列化

项目结构

数据结构信息

执行效果

项目源码

开发环境


定义

序列化:将对象或数据结构转换为二进制序列
反序列化:二进制序列转换为对象或数据结构

使对象或数据结构更方便地在网络上传输或者保存在本地文件中。

本文展示通过序列化将自定义数据结构序列化到硬盘文件中,再从文件反序列出来还原数据信息。

Qt中序列化与反序列化

Qt中使用QDataStream类实现对象序列化;

序列化:

QFile file("file.rx");           //定义文件路径
file.open(QIODevice::WriteOnly); //以只写模式打开
QDataStream out(&file);          //定义数据流
out << QString("hello world!");  //写入内容

反序列化:

QFile file("datas.rx");         //定义文件路径
file.open(QIODevice::ReadOnly); //以只读模式打开
QDataStream in(&file);          //定义数据流
QString str;                    //创建字符串用于接收
in >> str;                      //读出内容

自定义数据结构序列化与反序列化

QDataStream只能序列化基本类型,对于自定义类或者数据结构则需要在自定义类中声明并实现友元函数friend:

friend QDataStream &operator<<(QDataStream &stream, const ParamsData &data);  //序列化
friend QDataStream &operator>>(QDataStream &stream, ParamsData &data);        //反序列胡

QDataStream本身支持的数据类型如下:

bool
qint8
qint16
qint32
qint64
quint8
quint16
quint32
quint64
float
double
const char *
QBitArray
QBrush
QByteArray
QColor
QCursor
QDate
QDateTime
QEasingCurve
QFont
QGenericMatrix
QHash<Key, T>
QIcon
QImage
QKeySequence
QLinkedList<T>
QList<T>
QMap<Key, T>
QMargins
QMatrix4x4
QPair<T1, T2>
QPalette
QPen
QPicture
QPixmap
QPoint
QQuaternion
QRect
QRegExp
QRegularExpression
QRegion
QSize
QString
QTime
QTransform
QUrl
QVariant
QVector2D
QVector3D
QVector4D
QVector<T>

原文地址:https://doc.qt.io/qt-5/datastreamformat.html

项目结构

CommonData类:公共类,用于存储数据;方便项目中其他类文件调用,数据使用静态存储;

MainWindow类:使用CommonData中静态数据,包含UI界面,实现数据的序列化与反序列化;

数据结构信息

根据以上描述,定义如下数据struct,并声明实现friend友元函数:

注意:读和写的变量顺序必须一致

//定义静态数据结构
static struct ParamsData{QString m_paramFile="qwe";int m_imagenubth=-1;bool m_SysInitDone=false;int m_grabimgIdx=112;float m_axisNum=123.234f;bool m_homeState=true;QPoint mark1_Center=QPoint(23,23);double mark1_Radius=5.0008;friend QDataStream &operator<<(QDataStream &stream, const ParamsData &data)//序列化{stream << data.m_paramFile;stream << data.m_imagenubth;stream << data.m_SysInitDone;stream << data.m_grabimgIdx;stream << data.m_axisNum;stream << data.m_homeState;stream << data.mark1_Center;stream << data.mark1_Radius;return stream;}friend QDataStream &operator>>(QDataStream &stream, ParamsData &data)//反序列化{stream >> data.m_paramFile;stream >> data.m_imagenubth;stream >> data.m_SysInitDone;stream >> data.m_grabimgIdx;stream >> data.m_axisNum;stream >> data.m_homeState;stream >> data.mark1_Center;stream >> data.mark1_Radius;return stream;}
}paramsData;

界面如下:

CommonData.h

#ifndef COMMONDATA_H
#define COMMONDATA_H#include <QObject>
#include <QDataStream>//用于存储公共数据
class CommonData : public QObject
{Q_OBJECT
public:explicit CommonData(QObject *parent = nullptr);public://定义静态数据结构static struct ParamsData{QString m_paramFile="qwe";int m_imagenubth=-1;bool m_SysInitDone=false;int m_grabimgIdx=112;float m_axisNum=123.234f;bool m_homeState=true;QPoint mark1_Center=QPoint(23,23);double mark1_Radius=5.0008;friend QDataStream &operator<<(QDataStream &stream, const ParamsData &data)//序列化{stream << data.m_paramFile;stream << data.m_imagenubth;stream << data.m_SysInitDone;stream << data.m_grabimgIdx;stream << data.m_axisNum;stream << data.m_homeState;stream << data.mark1_Center;stream << data.mark1_Radius;return stream;}friend QDataStream &operator>>(QDataStream &stream, ParamsData &data)//反序列化{stream >> data.m_paramFile;stream >> data.m_imagenubth;stream >> data.m_SysInitDone;stream >> data.m_grabimgIdx;stream >> data.m_axisNum;stream >> data.m_homeState;stream >> data.mark1_Center;stream >> data.mark1_Radius;return stream;}}paramsData;};#endif // COMMONDATA_H

CommonData.cpp

#include "commondata.h"CommonData::CommonData(QObject *parent) : QObject(parent)
{}CommonData::ParamsData CommonData::paramsData;//此句需要,否则报错

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void PrintContent();private slots:void on_btn_Read_clicked();void on_btn_Write_clicked();void on_btn_ChangeVal_clicked();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "commondata.h"
#include <QFile>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_btn_Read_clicked()// 从文件中读取/初始化数据
{QFile file("data.sx");//文件在程序运行目录下if(file.exists())//如果文件存在 则从文件读取数据{file.open(QIODevice::ReadOnly);QDataStream input(&file);input >> CommonData::paramsData;file.close();//打印出各个变量的值qDebug() << QStringLiteral("打印出文件中读出的值.......");PrintContent();}else//如果文件不存在 则使用初始化数据{//打印出各个变量的值qDebug() << QStringLiteral("打印出初始化的值.......");PrintContent();}
}void MainWindow::on_btn_Write_clicked()//将数据写入文件保存
{QFile file("data.sx");//文件在程序运行目录下file.open(QIODevice::WriteOnly);QDataStream output(&file);output << CommonData::paramsData;file.close();
}void MainWindow::on_btn_ChangeVal_clicked()//改变数据的值,查看是否能正确写入文件并读出
{CommonData::paramsData.m_axisNum=234.123f;CommonData::paramsData.m_homeState=false;CommonData::paramsData.m_paramFile="wer";CommonData::paramsData.m_grabimgIdx=113;CommonData::paramsData.m_imagenubth=168;CommonData::paramsData.mark1_Center=QPoint(66,88);CommonData::paramsData.mark1_Radius=6.08080808;CommonData::paramsData.m_SysInitDone=true;qDebug() << QStringLiteral("打印改变后的值.......");PrintContent();
}void MainWindow::PrintContent()//打印数据 便于调试查看
{qDebug() << CommonData::paramsData.m_axisNum;qDebug() << CommonData::paramsData.m_homeState;qDebug() << CommonData::paramsData.m_paramFile;qDebug() << CommonData::paramsData.m_grabimgIdx;qDebug() << CommonData::paramsData.m_imagenubth;qDebug() << CommonData::paramsData.mark1_Center;qDebug() << CommonData::paramsData.mark1_Radius;qDebug() << CommonData::paramsData.m_SysInitDone;
}

执行效果

/*执行步骤:1、没有文件,初始化数据结构2、改变数据结构的值3、写入文件4、读取文件,读出的为更改后的值
*/
"打印出初始化的值......."
123.234
true
"qwe"
112
-1
QPoint(23,23)
5.0008
false
"打印改变后的值......."
234.123
false
"wer"
113
168
QPoint(66,88)
6.08081
true
"打印出文件中读出的值......."
234.123
false
"wer"
113
168
QPoint(66,88)
6.08081
true

项目源码

GitHub地址:lizhifun/QtSerialize

开发环境

Author:Lizhifun

OS:Windows 10 家庭中文版

Compiler:Microsoft Visual C++ Compiler 15.9.28307.1259(amd64)

Kit:Desktop Qt 5.14.2 MSVC2017 64bit

Qt Creator:4.11.1


http://chatgpt.dhexx.cn/article/Z580sHha.shtml

相关文章

序列化作用

没有implements Serializable&#xff0c;你就不能通过rmi(包括ejb)提供远程调用。 serialization 允许你将实现了Serializable接口的对象转换为字节序列&#xff0c;这些字节序列可以被完全存储以备以后重新生成原来的对象。 serialization不但可以在本机做&#…

PHP反序列化

定义 序列化&#xff08;串行化&#xff09;&#xff1a;是将变量转换为可保存或传输的字符串的过程&#xff1b; 反序列化&#xff08;反串行化&#xff09;&#xff1a;就是在适当的时候把这个字符串再转化成原来的变量使用&#xff1b; 这两个过程结合起来&#xff0c;可以轻…

Spark序列化简介

参考文章&#xff1a;Spark序列化 spark之kryo 序列化 Spark序列化入门 1. 什么是序列化和序列化? 序列化是什么 序列化的作用就是可以将对象的内容变成二进制, 存入文件中保存反序列化指的是将保存下来的二进制对象数据恢复成对象 序列化对对象的要求 对象必须实现 Serial…

谈谈序列化的作用

文章目录 1. 写在前面2. 问题阐述3. 解释3.1 一些不够完整的解释3.2 一种完整的解释3.2.1 去地址3.2.2 节省空间 4. 小节参考链接 1. 写在前面 我们应该都用过各种序列化&#xff08;serialization&#xff09;的方法&#xff08;如Python中的pickle.dumps&#xff09;&#x…

Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

遇到这个 Java Serializable 序列化这个接口&#xff0c;我们可能会有如下的问题 a&#xff0c;什么叫序列化和反序列化 b&#xff0c;作用。为啥要实现这个 Serializable 接口&#xff0c;也就是为啥要序列化 c&#xff0c;serialVersionUID 这个的值到底是在怎么设置的&#…

cas 原理分析

CAS 原理分析 1、了解java中锁的类型 1.1 悲观锁(Pessimistic Lock) 顾名思义&#xff0c;就是很悲观&#xff0c;假定会发生并发冲突&#xff0c;屏蔽一切可能违反数据完整性的操作&#xff0c;每次去拿数据的时候都认为别人会修改&#xff0c;所以每次在拿数据的时候都会上…

JAVA中的CAS算法

java 中的线程之间的栈空间是相互独立&#xff0c;堆空间是共享的 V&#xff1a;内存值就是主内存中i值 A&#xff1a;预估值(期望值)就是子线程拿到主内存的值&#xff08;读取到高速缓存中的值&#xff09; B&#xff1a;更新值是子线程拿到i值后,修改i的值 假设有两个线程…

面试:CAS算法原理

1、什么是CAS&#xff1f; CAS&#xff1a;Compare and Swap&#xff0c;即比较再交换。 jdk5增加了并发包java.util.concurrent.*&#xff0c;其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的&#x…

CAS原理详解

CAS介绍 CAS全称是Compare And Swap&#xff0c;它的实现和它的字面意思一样&#xff0c;先比较后交换&#xff0c;它是CPU硬件层面的一种指令&#xff0c;从CPU层面能保证"比较并更新"这一段操作的原子性。 与synchronized关键字比较不同是synchronized是一种悲观锁…

CAS算法与ABA问题

锁是用来做并发最简单的方式&#xff0c;当然代价也是最高的。 独占锁是一种悲观锁&#xff0c;synchronized就是一种独占锁&#xff1b;它假设最坏的情况&#xff0c;并且只有在确保其它线程不会造成干扰的情况下执行&#xff0c;会导致其它所有需要锁的线程挂起直到持有锁的…

CAS算法-实现原理

目录 CAS是什么&#xff1f; CAS解决了什么问题&#xff1f; CAS存在什么问题&#xff1f; CAS有哪些应用场景&#xff1f; cas的实现 最后 CAS是什么&#xff1f; CAS的全称为Compare and swap 比较并交换。CAS又经常被称为乐观锁&#xff0c;主要的三个变量&#xff0c;内存值…

并发策略-CAS算法

对于并发控制而言&#xff0c;我们平时用的锁&#xff08;synchronized&#xff0c;Lock&#xff09;是一种悲观的策略。它总是假设每一次临界区操作会产生冲突&#xff0c;因此&#xff0c;必须对每次操作都小心翼翼。如果多个线程同时访问临界区资源&#xff0c;就宁可牺牲性…

深入理解CAS算法原理

转载自 深入理解CAS算法原理 1、什么是CAS&#xff1f; CAS&#xff1a;Compare and Swap&#xff0c;即比较再交换。 jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证…

CAS操作原理

1、什么是CAS&#xff1f; CAS&#xff1a;Compare and Swap&#xff0c;即比较再交换。 jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的&#xff0c;这是一…

CAS原理

一、CAS 1.1 CAS概述和作用 CAS的全称是&#xff1a; Compare And Swap(比较相同再交换)。是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。 CAS的作用&#xff1a;CAS可以将比较和交换转换为原子操作&#xff0c;这个原子操作直接由CPU保证。 CAS可以保证…

CAS算法详解

CAS算法 1、CAS概念&#xff1a; CAS是CompareAndSwap的缩写&#xff0c;中文意思是&#xff1a;比较并替换。当要进行CAS操作时&#xff0c;先比较内存地址和原来预期的 地址比较&#xff0c;如果相同&#xff0c;表示这块内存地址没有被修改&#xff0c;可以用新地址替换&…

CAS的原理和使用

CAS 文章目录 CAS一、学习CAS首先了解原子类&#xff1f;1. 何为原子类 二、 CAS是什么1. CAS是什么2. CAS原理3. 使用CAS实例代码4. CAS属于硬件级别保证5. 源码分析 三、CAS底层原理&#xff1f;如果知道&#xff0c;谈谈你对UnSafe的理解1. UnSafe2. 我们知道i线程不安全的&…

对cas算法的理解

cas算法主要关心3个值&#xff1a;内存值V&#xff0c;预期值A&#xff0c;要更新的新值B 如下图所示&#xff1a; 注&#xff1a;t1&#xff0c;t2线程是同时更新同一变量56的值 因为t1和t2线程都同时去访问同一变量56&#xff0c;所以他们会把主内存的值完全拷贝一份到自己…

CAS原理分析

CAS的英文为Compare and Swap 翻译为比较并交换。 CAS加volatile关键字是实现并发包的基石。没有CAS就不会有并发包&#xff0c;synchronized是一种独占锁、悲观锁&#xff0c;java.util.concurrent中借助了CAS指令实现了一种区别于synchronized的一种乐观锁。 什么是乐观锁与…

CAS详解

一、CAS概念 1.1 CAS是什么 Compare And Swap 比较并交换 1. 如果线程的期望值跟物理内存的真实值一样&#xff0c;就更新值到物理内存当中&#xff0c;并返回true 2. 如果线程的期望值跟物理内存的真实值不一样&#xff0c;返回false&#xff0c;那么本次修改失败&#xf…