Qt/halcon 总结halcon字典数据用法和QDataSteam序列化与反序列化结构体实例

这就是一篇记录学习Halcon dict 字典在Qt/C++环境中处理数据的笔记总结,以及实际项目中开发遇到的问题延伸汇总。

目录导读

一、Halcon字典数据的增删查改

当前示例适用于halcon 24.0左右版本

1.创建halcon字段并赋值

cpp 复制代码
HTuple  hv_DictHandle;
//hv_DictHandle=dict{}
//创建一个空字典`
CreateDict(&hv_DictHandle);
//1. 添加键值对等同于修改
SetDictTuple(hv_DictHandle, "score", 95);
//2.添加图像对象
HObject  ho_Image;
ReadImage(&ho_Image, "particle");
SetDictObject(ho_Image, hv_DictHandle, "particle_image");

2.读取字段数据

cpp 复制代码
HTuple  hv_Exists, hv_ScoreValue;
//!  判断是否有当前字段,如果明知有可以直接提取`
GetDictParam(hv_DictHandle, "key_exists", "score", &hv_Exists);
if (0 != hv_Exists)
{ 
    GetDictTuple(hv_DictHandle, "score", &hv_ScoreValue); 
    //! 或者 
    hv_ScoreValue=hv_DictHandle.TupleGetDictTuple("epoch") ; 
} 

3.删除键值对

cpp 复制代码
RemoveDictKey(hv_DictHandle, "score");

4.复制HTuple,不限于字典类型

直接使用=号赋值,相当于指针引用。

cpp 复制代码
HTuple hv_DLDataset1;
CopyDict(hv_DictHandle, HTuple(), HTuple(), &hv_DLDataset1);

5.读取和写入HTuple 结构数据

cpp 复制代码
WriteDict(hv_DictHandle, "Text_DictHandle.hdict", HTuple(), HTuple());
ReadDict("Text_DictHandle.hdict", HTuple(), HTuple(), &hv_DictHandle);

6.HTuple字典插入元组数据

cpp 复制代码
//替换某处值
SetDictTupleAt(hv_DictHandle, "元组名称", 0, HTuple());
//被替换后重新添加
SetDictTuple(hv_DictHandle, "元组名称", (hv_DictHandle.TupleGetDictTuple("元组名称")).TupleConcat(hv_ImageItem));

7.HTuple字典元组删除某项

cpp 复制代码
 HTuple hv_indexss = -1;
  //查找第一个
  TupleFindFirst(hv_DictHandle.TupleGetDictTuple("元组名称"), hv_ImageItem, &hv_indexss);
  //移除索引项
  //tuple_remove (DictHandle.Mapdepot, indexss, Reduced)
  TupleRemove(hv_DictHandle.TupleGetDictTuple("元组名称"), hv_indexss, &hv___Tmp_Ctrl_0);
  //更新
  SetDictTuple(hv_DictHandle, "元组名称", hv___Tmp_Ctrl_0);

8.HTuple字典遍历所有字段

cpp 复制代码
//! 获取所有键值
GetDictParam(hv_Divide, "keys", HTuple(), &hv_Keys);
HTuple end_val75 = (hv_Keys.TupleLength())-1;
HTuple step_val75 = 1;
for (hv_Index=0; hv_Index.Continue(end_val75, step_val75); hv_Index += step_val75)
{
	//! 获取数据类型
    GetDictParam(hv_Divide, "key_data_type", HTuple(hv_Keys[hv_Index]), &hv_DataType);
    //! 获取数据值
    GetDictTuple(hv_Divide, HTuple(hv_Keys[hv_Index]), &hv_Value);
}

9.HTuple字典元组数据遍历

cpp 复制代码
GetDictTuple(hv_DictHandle, "TrainingModel", &hv_TrainingModel);
qDebug()<<"hv_TrainingModel: "<<(int)hv_TrainingModel.TupleLength();
for (int i = 0; i < hv_TrainingModel.TupleLength(); i++)
{
   HTuple TrainingModel=hv_TrainingModel[i];
}

10.Tuple 数据转换 QString,int,Double

从Tuple数据类型转换成QT中常用的数据类型,
如果Tuple中的数据类型与你转换的数据类型不一致,会导致异常需要注意

cpp 复制代码
QString Train_Name=QString::fromUtf8(hv_DictHandle.TupleGetDictTuple("Train_Name").S());
int Channels=hv_DictHandle.TupleGetDictTuple("Channels").I();
double num_epochs=hv_DictHandle.TupleGetDictTuple("num_epochs").D();

二、QDataSteam序列化与反序列化结构体

一开始我是在项目中使用Tuple 字典保存项目结构,这样也能保存训练的数据和模型数据,而且Tuple自带线程安全,哪怕是在改都可以。

但是当告诉我软件需要兼容其他深度训练框架的时候,就不太适用了

就必须使用结构体来保存项目结构了,这意味着软件后期需要大改,淦。

(╯°Д°)╯︵ ┻━┻

于是仔细研究了下QDataSteam序列化与反序列化结构体,争取尽量减少改动,

于是整理了一下具体实现,┬─┬ ノ('-'ノ)

至于为什么不用sqlite或xml,json来保存...

因为用得多了显得捞...

1.定义一个复杂的结构体

定义一个多个数据,嵌套其他结构的结构体 DictHandData :

用来模拟实际项目的复杂结构。

cpp 复制代码
struct MapDepot
{
    int     image_id;
    QString image_file_name;
    int     image_label_id;
    QString split;
};

struct Classes
{
    QString class_names;
    int     class_ids;
    QString class_color;
    QString shortcutkey;
};

struct Splits
{
    QString split_name;
    int     train_num;
    int     train_percentum;
    int     validation_num;
    int     validation_percentum;
    int     test_num;
    int     test_percentum;
};

struct TrainInfo
{
    double  epoch;
    double  num_epochs;
    double  num_iterations_per_epoch;
    double  mean_loss;
    int     mean_loss_samples;
    int     start_epoch;
    double  start_time;
    double  time_elapsed;
};

struct XProgres
{
    QString Natural_Model_Path;
    QString ExampleDataDir;
    QString DL_Dataset;
    QString DL_Preprocess_Param;
    QString Current_State;
    QString Operating_State;
    QList<TrainInfo> TrainInfos;
};

struct Trains
{
    QString Train_Name;
    QString Natural_Model;
    int     Image_Width;
    int     Image_Height;
    int     Channels;
    QString Facility_Name;
    int     Seed_Rand;
    int     Num_Epochs;
    int     Num_Batch;
    int     Num_Iterations;
    double  Learning_Rate;
    QString Correlation_Splitting;
    QString Current_State;
    QString Operating_State;
    int     Current_Schedule;
    QString Current_Assessment;

    XProgres Progres;
};



//! 自定义多重结构体
struct DictHandData
{
    int ProjectType;
    QString ProjectName;
    QString ProjectPath;
    QString ProjectDir;
    QString ProjectNode;

    //! 图元集合
    QList<MapDepot> MapDepotLists;
    QList<Classes>  ClassessLists;
    QList<Splits>   SplitItems;
    QList<Trains>   TrainingModel;

};

2.重写operator <<和>>操作符

通过重写operator <<operator >>操作符实现结构体的序列化与反序列化:

注意:操作符函数声明为 inline,防止多重定义:

看着写的多,实际上千篇一律,按照顺序输出,写入就行了。

cpp 复制代码
//! 操作符函数声明为 inline,防止多重定义:
//! 定义写入MapDepot
inline QDataStream& operator<<(QDataStream& out, const MapDepot& config) {
    out << config.image_id << config.image_file_name
        << config.image_label_id << config.split;
    return out;
}

//! 定义读取MapDepot
inline QDataStream& operator>>(QDataStream& in, MapDepot& config) {
    in >> config.image_id >> config.image_file_name
        >> config.image_label_id >> config.split;
    return in;
}

//! 定义写入 Classes
inline QDataStream& operator<<(QDataStream& out, const Classes& config) {
    out << config.class_names << config.class_ids
        << config.class_color << config.shortcutkey;
    return out;
}

//! 定义读取 Classes
inline QDataStream& operator>>(QDataStream& in, Classes& config) {
    in >> config.class_names >> config.class_ids
        >> config.class_color >> config.shortcutkey;
    return in;
}

//! 定义写入 Splits
inline QDataStream& operator<<(QDataStream& out, const Splits& config) {
    out << config.split_name
        << config.train_num << config.train_percentum
        << config.validation_num << config.validation_percentum
        << config.test_num << config.test_percentum;
    return out;
}

//! 定义读取 Splits
inline QDataStream& operator>>(QDataStream& in, Splits& config) {
    in >> config.split_name
        >> config.train_num >> config.train_percentum
        >> config.validation_num >> config.validation_percentum
        >> config.test_num >> config.test_percentum;
    return in;
}

//! 定义写入 TrainInfo
inline QDataStream& operator<<(QDataStream& out, const TrainInfo& config) {
    out << config.epoch<< config.num_epochs
        << config.num_iterations_per_epoch << config.mean_loss
        << config.mean_loss_samples << config.start_epoch
        << config.start_time << config.time_elapsed;
    return out;
}

//! 定义读取 TrainInfo
inline QDataStream& operator>>(QDataStream& in, TrainInfo& config) {
    in >> config.epoch >> config.num_epochs
        >> config.num_iterations_per_epoch >> config.mean_loss
        >> config.mean_loss_samples >> config.start_epoch
        >> config.start_time >> config.time_elapsed;
    return in;
}

//! 定义写入 XProgres
inline QDataStream& operator<<(QDataStream& out, const XProgres& config) {
    out << config.Natural_Model_Path<< config.ExampleDataDir
        << config.DL_Dataset << config.DL_Preprocess_Param
        << config.Current_State << config.Operating_State
        << config.TrainInfos;
    return out;
}

//! 定义读取 XProgres
inline QDataStream& operator>>(QDataStream& in, XProgres& config) {
    in >> config.Natural_Model_Path >> config.ExampleDataDir
        >> config.DL_Dataset >> config.DL_Preprocess_Param
        >> config.Current_State >> config.Operating_State
        >> config.TrainInfos;
    return in;
}


//! 定义写入 Trains
inline QDataStream& operator<<(QDataStream& out, const Trains& config) {
    out << config.Train_Name<< config.Natural_Model
        << config.Image_Width << config.Image_Height
        << config.Channels << config.Facility_Name
        << config.Seed_Rand << config.Num_Epochs
        << config.Num_Batch << config.Num_Iterations
        << config.Learning_Rate << config.Correlation_Splitting
        << config.Current_State << config.Operating_State
        << config.Current_Schedule << config.Current_Assessment
        << config.Progres;
    return out;
}

//! 定义读取 Trains
inline QDataStream& operator>>(QDataStream& in, Trains& config) {
    in  >> config.Train_Name >> config.Natural_Model
        >> config.Image_Width >> config.Image_Height
        >> config.Channels >> config.Facility_Name
        >> config.Seed_Rand >> config.Num_Epochs
        >> config.Num_Batch >> config.Num_Iterations
        >> config.Learning_Rate >> config.Correlation_Splitting
        >> config.Current_State >> config.Operating_State
        >> config.Current_Schedule >> config.Current_Assessment
        >> config.Progres;
    return in;
}


//! 定义写入 DictHandData
inline QDataStream& operator<<(QDataStream& out, const DictHandData& config) {
    out << config.ProjectType<< config.ProjectName
        << config.ProjectPath << config.ProjectDir
        << config.ProjectNode << config.MapDepotLists
        << config.ClassessLists << config.SplitItems
        << config.TrainingModel;
    return out;
}

//! 定义读取 DictHandData
inline QDataStream& operator>>(QDataStream& in, DictHandData& config) {
    in  >> config.ProjectType >> config.ProjectName
        >> config.ProjectPath >> config.ProjectDir
        >> config.ProjectNode >> config.MapDepotLists
        >> config.ClassessLists >> config.SplitItems
        >> config.TrainingModel;
    return in;
}

而通过这种方式写入保存的数据,在txt文本中依旧能看到具体的文件路径或名称,这得修改一下,至少内容不可见。

2.从新修改operator 操作符 使用Base64简单加密字符串

使用Base64和utf8简单加密字符串防止出现具体内容。

甚至可以使用其他的加密库实现.这里只介绍了最简单的用法

cpp 复制代码
//! 使用Base64加密
//! 操作符函数声明为 inline,防止多重定义:
//! 定义写入MapDepot
inline QDataStream& operator<<(QDataStream& out, const MapDepot& config) {
    out << config.image_id << config.image_file_name.toUtf8().toBase64()
        << config.image_label_id << config.split.toUtf8().toBase64();
    return out;
}

//! 定义读取MapDepot
inline QDataStream& operator>>(QDataStream& in, MapDepot& config) {
    QByteArray image_file_name;
    QByteArray split;
    in >> config.image_id >> image_file_name
        >> config.image_label_id >> split;
    config.image_file_name=QString::fromUtf8(QByteArray::fromBase64(image_file_name));
    config.split=QString::fromUtf8(QByteArray::fromBase64(split));
    return in;
}

//! 定义写入 Classes
inline QDataStream& operator<<(QDataStream& out, const Classes& config) {
    out << config.class_names.toUtf8().toBase64() << config.class_ids
        << config.class_color.toUtf8().toBase64() << config.shortcutkey.toUtf8().toBase64();
    return out;
}

//! 定义读取 Classes
inline QDataStream& operator>>(QDataStream& in, Classes& config) {
    QByteArray class_names;
    QByteArray class_color;
    QByteArray shortcutkey;
    in >> class_names >> config.class_ids
        >> class_color >> shortcutkey;

    config.class_names=QString::fromUtf8(QByteArray::fromBase64(class_names));
    config.class_color=QString::fromUtf8(QByteArray::fromBase64(class_color));
    config.shortcutkey=QString::fromUtf8(QByteArray::fromBase64(shortcutkey));
    return in;
}

//! 定义写入 Splits
inline QDataStream& operator<<(QDataStream& out, const Splits& config) {
    out << config.split_name.toUtf8().toBase64()
        << config.train_num << config.train_percentum
        << config.validation_num << config.validation_percentum
        << config.test_num << config.test_percentum;
    return out;
}

//! 定义读取 Splits
inline QDataStream& operator>>(QDataStream& in, Splits& config) {
       QByteArray split_name;

    in >> split_name
        >> config.train_num >> config.train_percentum
        >> config.validation_num >> config.validation_percentum
        >> config.test_num >> config.test_percentum;

       config.split_name=QString::fromUtf8(QByteArray::fromBase64(split_name));
    return in;
}

//! 定义写入 TrainInfo
inline QDataStream& operator<<(QDataStream& out, const TrainInfo& config) {
    out << config.epoch<< config.num_epochs
        << config.num_iterations_per_epoch << config.mean_loss
        << config.mean_loss_samples << config.start_epoch
        << config.start_time << config.time_elapsed;
    return out;
}

//! 定义读取 TrainInfo
inline QDataStream& operator>>(QDataStream& in, TrainInfo& config) {
    in >> config.epoch >> config.num_epochs
        >> config.num_iterations_per_epoch >> config.mean_loss
        >> config.mean_loss_samples >> config.start_epoch
        >> config.start_time >> config.time_elapsed;
    return in;
}

//! 定义写入 XProgres
inline QDataStream& operator<<(QDataStream& out, const XProgres& config) {
    out << config.Natural_Model_Path.toUtf8().toBase64()<< config.ExampleDataDir.toUtf8().toBase64()
        << config.DL_Dataset.toUtf8().toBase64() << config.DL_Preprocess_Param.toUtf8().toBase64()
        << config.Current_State.toUtf8().toBase64() << config.Operating_State.toUtf8().toBase64()
        << config.TrainInfos;
    return out;
}

//! 定义读取 XProgres
inline QDataStream& operator>>(QDataStream& in, XProgres& config) {
    QByteArray Natural_Model_Path;
    QByteArray ExampleDataDir;
    QByteArray DL_Dataset;
    QByteArray DL_Preprocess_Param;
    QByteArray Current_State;
    QByteArray Operating_State;
    in >> Natural_Model_Path >> ExampleDataDir
        >> DL_Dataset >> DL_Preprocess_Param
        >> Current_State >> Operating_State
        >> config.TrainInfos;

    config.Natural_Model_Path=QString::fromUtf8(QByteArray::fromBase64(Natural_Model_Path));
    config.ExampleDataDir=QString::fromUtf8(QByteArray::fromBase64(ExampleDataDir));
    config.DL_Dataset=QString::fromUtf8(QByteArray::fromBase64(DL_Dataset));
    config.DL_Preprocess_Param=QString::fromUtf8(QByteArray::fromBase64(DL_Preprocess_Param));
    config.Current_State=QString::fromUtf8(QByteArray::fromBase64(Current_State));
    config.Operating_State=QString::fromUtf8(QByteArray::fromBase64(Operating_State));
    return in;
}


//! 定义写入 Trains
inline QDataStream& operator<<(QDataStream& out, const Trains& config) {
    out << config.Train_Name.toUtf8().toBase64()<< config.Natural_Model.toUtf8().toBase64()
        << config.Image_Width << config.Image_Height
        << config.Channels << config.Facility_Name.toUtf8().toBase64()
        << config.Seed_Rand << config.Num_Epochs
        << config.Num_Batch << config.Num_Iterations
        << config.Learning_Rate << config.Correlation_Splitting.toUtf8().toBase64()
        << config.Current_State.toUtf8().toBase64() << config.Operating_State.toUtf8().toBase64()
        << config.Current_Schedule << config.Current_Assessment.toUtf8().toBase64()
        << config.Progres;
    return out;
}

//! 定义读取 Trains
inline QDataStream& operator>>(QDataStream& in, Trains& config) {
    QByteArray Train_Name;
    QByteArray Natural_Model;
    QByteArray Facility_Name;
    QByteArray Correlation_Splitting;
    QByteArray Current_State;
    QByteArray Operating_State;
    QByteArray Current_Assessment;
    in  >> Train_Name >> Natural_Model
        >> config.Image_Width >> config.Image_Height
        >> config.Channels >> Facility_Name
        >> config.Seed_Rand >> config.Num_Epochs
        >> config.Num_Batch >> config.Num_Iterations
        >> config.Learning_Rate >> Correlation_Splitting
        >> Current_State >> Operating_State
        >> config.Current_Schedule >> Current_Assessment
        >> config.Progres;

    config.Train_Name=QString::fromUtf8(QByteArray::fromBase64(Train_Name));
    config.Natural_Model=QString::fromUtf8(QByteArray::fromBase64(Natural_Model));
    config.Facility_Name=QString::fromUtf8(QByteArray::fromBase64(Facility_Name));
    config.Correlation_Splitting=QString::fromUtf8(QByteArray::fromBase64(Correlation_Splitting));
    config.Current_State=QString::fromUtf8(QByteArray::fromBase64(Current_State));
    config.Operating_State=QString::fromUtf8(QByteArray::fromBase64(Operating_State));
    config.Current_Assessment=QString::fromUtf8(QByteArray::fromBase64(Current_Assessment));
    return in;
}


//! 定义写入 DictHandData
inline QDataStream& operator<<(QDataStream& out, const DictHandData& config) {
    out << config.ProjectType<< config.ProjectName.toUtf8().toBase64()
        << config.ProjectPath.toUtf8().toBase64() << config.ProjectDir.toUtf8().toBase64()
        << config.ProjectNode.toUtf8().toBase64() << config.MapDepotLists
        << config.ClassessLists << config.SplitItems
        << config.TrainingModel;
    return out;
}

//! 定义读取 DictHandData
inline QDataStream& operator>>(QDataStream& in, DictHandData& config) {
    QByteArray ProjectName;
    QByteArray ProjectPath;
    QByteArray ProjectDir;
    QByteArray ProjectNode;

    in  >> config.ProjectType >> ProjectName
        >> ProjectPath >> ProjectDir
        >> ProjectNode >> config.MapDepotLists
        >> config.ClassessLists >> config.SplitItems
        >> config.TrainingModel;

    config.ProjectName=QString::fromUtf8(QByteArray::fromBase64(ProjectName));
    config.ProjectPath=QString::fromUtf8(QByteArray::fromBase64(ProjectPath));
    config.ProjectDir=QString::fromUtf8(QByteArray::fromBase64(ProjectDir));
    config.ProjectNode=QString::fromUtf8(QByteArray::fromBase64(ProjectNode));
    return in;
}

#endif

使用 QDataSteam 序列化结构体

使用 QDataSteam 序列化结构体快速写入文本文件中:

cpp 复制代码
 	QFile file("HandDatas.txt");
 	DictHandData HandDatas;
 	//! 确保HandDatas结构体有数据
    if (file.open(QIODevice::WriteOnly)) {
        QDataStream out(&file);
        out.setByteOrder(QDataStream::BigEndian);
        out.setVersion(QDataStream::Qt_5_13);
        out<<HandDatas;
        file.close();
    }

使用 QDataSteam 反序列化结构体

使用 QDataSteam 从文件中加载结构体数据:

cpp 复制代码
 	QFile file("HandDatas.txt");
 	DictHandData HandDatas;
    if (file.open(QIODevice::ReadOnly)) {

        QDataStream out(&file);
        out.setByteOrder(QDataStream::BigEndian);
        out.setVersion(QDataStream::Qt_5_13);
        out>>HandDatas;
        file.close();
    }

简单,快速,高效!

三、其他

1.重写QDebug& operator<<操作符,打印结构体

为了快速的验证数据经过序列化和反序列化之后有没有问题,

于是又重写 inline QDebug& operator<<(QDebug& out, const 结构体& config)方法

实现直接qDebug()i打印结构体中的数据。

cpp 复制代码
//! 定义打印输出
inline QDebug& operator<<(QDebug& out, const MapDepot& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "MapDepot("
        << "\n  image_id: " << config.image_id
        << "\n  image_file_name: " << config.image_file_name
        << "\n  image_label_id: " << config.image_label_id
        << "\n  split: " << config.split
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const Classes& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "Classes("
        << "\n  class_names: " << config.class_names
        << "\n  class_ids: " << config.class_ids
        << "\n  class_color: " << config.class_color
        << "\n  shortcutkey: " << config.shortcutkey
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const Splits& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "Splits("
        << "\n  split_name: " << config.split_name
        << "\n  train_num: " << config.train_num
        << "\n  train_percentum: " << config.train_percentum
        << "\n  validation_num: " << config.validation_num
        << "\n  validation_percentum: " << config.validation_percentum
        << "\n  test_num: " << config.test_num
        << "\n  test_percentum: " << config.test_percentum
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const TrainInfo& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "TrainInfo("
        << "\n  epoch: " << config.epoch
        << "\n  num_epochs: " << config.num_epochs
        << "\n  num_iterations_per_epoch: " << config.num_iterations_per_epoch
        << "\n  mean_loss: " << config.mean_loss
        << "\n  mean_loss_samples: " << config.mean_loss_samples
        << "\n  start_epoch: " << config.start_epoch
        << "\n  start_time: " << config.start_time
        << "\n  time_elapsed: " << config.time_elapsed
        << "\n)";
    return out;
}


inline QDebug& operator<<(QDebug& out, const XProgres& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "XProgres("
        << "\n  Natural_Model_Path: " << config.Natural_Model_Path
        << "\n  ExampleDataDir: " << config.ExampleDataDir
        << "\n  DL_Dataset: " << config.DL_Dataset
        << "\n  DL_Preprocess_Param: " << config.DL_Preprocess_Param
        << "\n  Current_State: " << config.Current_State
        << "\n  Operating_State: " << config.Operating_State
        << "\n  TrainInfos: " << config.TrainInfos
        << "\n)";
    return out;
}


inline QDebug& operator<<(QDebug& out, const Trains& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "Trains("
        << "\n  Train_Name: " << config.Train_Name
        << "\n  Natural_Model: " << config.Natural_Model
        << "\n  Image_Width: " << config.Image_Width
        << "\n  Image_Height: " << config.Image_Height
        << "\n  Channels: " << config.Channels
        << "\n  Facility_Name: " << config.Facility_Name
        << "\n  Seed_Rand: " << config.Seed_Rand
        << "\n  Num_Epochs: " << config.Num_Epochs
        << "\n  Num_Batch: " << config.Num_Batch
        << "\n  Num_Iterations: " << config.Num_Iterations
        << "\n  Learning_Rate: " << config.Learning_Rate
        << "\n  Correlation_Splitting: " << config.Correlation_Splitting
        << "\n  Current_State: " << config.Current_State
        << "\n  Operating_State: " << config.Operating_State
        << "\n  Current_Schedule: " << config.Current_Schedule
        << "\n  Current_Assessment: " << config.Current_Assessment
        << "\n  Progres: " << config.Progres
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const DictHandData& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "DictHandData("
        << "\n  ProjectType: " << config.ProjectType
        << "\n  ProjectName: " << config.ProjectName
        << "\n  ProjectPath: " << config.ProjectPath
        << "\n  ProjectDir: " << config.ProjectDir
        << "\n  ProjectNode: " << config.ProjectNode
        << "\n  MapDepotLists: " << config.MapDepotLists
        << "\n  ClassessLists: " << config.ClassessLists
        << "\n  SplitItems: " << config.SplitItems
        << "\n  TrainingModel: " << config.TrainingModel
        << "\n)";
    return out;
}

调用

打印所有数据

cpp 复制代码
    //!同HTuple字典数据字段 结构体
    DictHandData HandDatas;
   	qDebug()<<" <- DictHandData -> ";
    qDebug().noquote() <<HandDatas;

总结

通过QDataSteam序列化与反序列化项目结构体,能最大的减少当结构体发生改变的时候,重新修改加载和保存函数。减少工作量。

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能14 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G14 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt