Qt以Json(JsonArray)格式向数据库添加图片数据(十六进制)及回显(序列化及反序列化)(解决方案)

这是一篇关于讲解"Qt以Json(JsonArray)格式向数据库添加图片数据(十六进制)及回显"的解决方案。

原因

在进行编程时,想将本地图片资源以Json格式保存到数据库,这样在不同的终端,都可以使用该数据库读取图片。

实现之前,先上网查下是否有可用示例,经过查阅,发现只有单个图片的序列化存储。而无以JsonArray进行存储的示例。既然没有,那就只有自己实现了。

说做就做,先将需求分解:

  1. 数据库表设计
  2. 数据的存储
  3. 数据的读取

实现

1. 数据库表设计

既然用于测试,那就随机创建个3列的表吧,关于对图片资源的字段类型,可以设置为TEXT。

cpp 复制代码
    QSqlDatabase m_db = QSqlDatabase::addDatabase("QSQLITE", "pngJsonArrayTest");
    if (!m_db.driver()->hasFeature(QSqlDriver::Transactions)) {
        qDebug() << "Database does not support transactions.";
        // handle lack of transaction support
    }
    m_db.setDatabaseName("./pngJsonArrayTest.db");
    m_db.open();

    QSqlQuery query(m_db);
    QString strQuery = QString("create table '%1' ('%2' TEXT,'%3' TEXT,'%4' TEXT)").arg("goodLucky", "f1", "f2", "pngJsonInfo");
    query.exec(strQuery);

2. 数据的存储

在进行存储前,首先得知道JsonValue、JsonArray和QByteArray的用法。

2.1 QJsonValue
cpp 复制代码
    QJsonValue(Type = Null);
    QJsonValue(bool b);
    QJsonValue(double n);
    QJsonValue(int n);
    QJsonValue(qint64 n);
    QJsonValue(const QString &s);
    QJsonValue(QLatin1String s);
    QJsonValue(const QJsonArray &a);
    QJsonValue(const QJsonObject &o);

QJsonValue存储的类型除了基本类型,还可以存储QJsonArray和QJsonObject.

2.2 QJsonArray

QJsonArray存储数据有很多个接口,以下是两种常用的。

cpp 复制代码
void QJsonArray::insert(int i, const QJsonValue &value);

在数组的索引位置i插入值。如果i为0,则将该值添加到数组中。如果i是size(),则该值被附加到数组中。

cpp 复制代码
void QJsonArray::push_back(const QJsonValue &value);

这个函数是为了兼容STL而提供的。它相当于append(value),将值追加到数组中。

2.2 QByteArray

QByteArray可用于存储原始字节(包括'\0')和传统的8位'\0'结尾的字符串。使用QByteArray比使用const char *方便得多。在后台,它总是确保数据后跟一个'\0'结束符,并使用隐式共享(写时复制)来减少内存使用并避免不必要的数据复制。

除了QByteArray, Qt还提供了QString类来存储字符串数据。在大多数情况下,QString是想要使用的类。它存储16位Unicode字符,使得在应用程序中存储非ascii /非latin -1字符变得容易。此外,QString在整个Qt API中使用。适合使用QByteArray的两种主要情况是:当需要存储原始二进制数据时,以及当内存保存非常重要时(例如,使用用于嵌入式Linux的Qt)。
QByteArray的用法和QString类似。

根据以上,可以看出,Json不可以存储QByteArray类型的数据。

因此我们要做的是,对QByteArray二进制或十六进制类型的数据的转换。

网上有很多QByteArray转QString的方法,但是基本都是对于文本字符串的,例如:QByteArray byte("Hello");

如果QByteArray为十六进制的数据,不能直接转化为QString,因为遇到\0时QString(str)转化时要么输出会为空,要么会缺失数据。

3. 数据的读取

查阅QByteArray帮助手册,发现其提供的有转换为16进制的接口:toHex()fromHex()

接下来就是具体实现:

3.1 存储
cpp 复制代码
// 序列化
        m_db.transaction();
        QJsonArray array;
        for(int i = 0; i < 3; ++i)
        {
	    // 资源路径
            QString strPath = "xxxx.png";
            QPixmap pixmap(strPath);
            QByteArray byteArray;
            QBuffer buffer(&byteArray);
            buffer.open(QIODevice::WriteOnly);
            QDataStream out(&buffer);
            out << pixmap;
            array.push_back(QString::fromLatin1(byteArray.toHex()));
        }
        QJsonDocument doc(array);
        QByteArray byteArray1 = doc.toJson();
        QSqlQuery query(m_db);
        query.prepare("INSERT INTO goodLucky (f1, f2, pngJsonInfo) "
                      "VALUES (:f1, :f2, :pngJsonInfo)");
        query.bindValue(":f1", "1");
        query.bindValue(":f2", "2");
        query.bindValue(":pngJsonInfo", byteArray);
        query.exec();
        m_db.commit();

经过以上转换,存储到数据库的就是十六进制的字符串。

3.3 读取
cpp 复制代码
// 反序列化
    QSqlQuery query("SELECT * FROM goodLucky", m_db);
    query.exec();

    while (query.next()) {
        QByteArray byteArray = query.value(2).toByteArray();
        QJsonDocument doc = QJsonDocument::fromJson(byteArray);
        for(QJsonValue value : doc.array()){
            QByteArray ba =  QByteArray::fromHex(value.toString().toLatin1()); 
            QBuffer buffer(&ba);
            buffer.open(QIODevice::ReadOnly);
            QDataStream in(&buffer);
            QPixmap pixmap;
            in >> pixmap;
        }
    }

以上就是反序列化过程。

结论

经过以上操作,就可以实现以JsonArray方式储存图片资源的十六进制形式。

Tips

如果数据库每个字段只是存储一个图片资源,直接可以储存不转换的QByteArray对象。

相关推荐
亦枫Leonlew8 分钟前
三维测量与建模笔记 - 3.1 相机标定基本概念
笔记·三维重建·1024程序员节·射影几何
EasyCVR1 小时前
国标GB28181视频平台EasyCVR私有化视频平台工地防盗视频监控系统方案
运维·科技·ffmpeg·音视频·1024程序员节·监控视频接入
V+zmm101343 小时前
社区养老服务小程序ssm+论文源码调试讲解
java·服务器·前端·javascript·小程序·毕业设计·1024程序员节
Lyqfor6 小时前
Redis学习:BitMap/HyperLogLog/GEO案例 、布隆过滤器BloomFilter、缓存预热+缓存雪崩+缓存击穿+缓存穿透
java·数据库·redis·学习·算法·缓存·1024程序员节
五条凪17 小时前
从零开始的LeetCode刷题日记:70. 爬楼梯
数据结构·算法·leetcode·职场和发展·1024程序员节
网安_秋刀鱼1 天前
PHP反序列化&原生类&字符串逃逸&框架反序列化利用
web安全·网络安全·php·1024程序员节
迷茫.4041 天前
第七章 利用CSS和多媒体美化页面
开发语言·javascript·ecmascript·1024程序员节
bitenum1 天前
【C/C++】【三种方法】模拟实现strlen
c语言·开发语言·c++·算法·青少年编程·visualstudio·1024程序员节
网安_秋刀鱼1 天前
JS渗透(安全)
前端·javascript·web安全·网络安全·1024程序员节
Matlab程序猿小助手1 天前
【MATLAB源码-第204期】基于matlab的语音降噪算法对比仿真,谱减法、维纳滤波法、自适应滤波法;参数可调。
开发语言·算法·matlab·cnn·语音识别·智能电视·1024程序员节