QT中使用json
Qt5 新增加了处理 JSON 的类,均以 QJson 开头,在 QtCore 模块中,不需要额外引入其它模块
类 |
类说明 |
QJsonDocument |
读写 JSON 文档 |
QJsonObject |
封装 JSON 对象 |
QJsonArray |
封装 JSON 数组 |
QJsonValue |
封装JSON 值 |
QJsonObject::iterator |
用于遍历 QJsonObject 的 STL 风格的非 const 遍历器 |
QJsonParseError |
报告 JSON 处理过程中出现的错误 |
在内存中有一个json格式字符串,我们想去操作json字符串,应该怎么操作?
头文件
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
1、首先需要一个JsonDocument类。即将字符串变成JsonDocument对象。
QByteArray——字节数组,在QT里面就相当于一个字符串
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR)
2、利用上面获得的JsonDocument对象调用
- object方法来将JsonDocument对象转化成json对象
- array方法来将JsonDocument对象转换成json数组
jaon中有两种类型,数组或者对象,具体参考json、cJSON
3、将json对象
通过键值对的键来获取值。
将json对象存入文件的操作
1、通过JsonDocument将json对象转换成字符串
// 使用jsonDocument对象加载json字符串
QJsonDocument doc = QJsonDocument::fromJson(json对象);
2、将字符串存入文件
整体流程图如下:
实现的例子——将json数据写入文件
json数据如下
{
“server”:{
"IP":"192.168.0.1",
"PORT":"9000"
}
}
第一步——创建json对象
// 创建json对象
QJsonObject obj;
//创建子对象
QJsonObject sub;
sub.insert("IP", QJsonValue("192.168.1.25"));
sub.insert("port", "9990");
//将子对象作为value放在json对象中
obj.insert("server", QJsonValue(sub));
第二步——构造json对象
//构造json对象
QJsonDocument doc(obj);
第三步——将json对象转成字符串
// 将json对象转换为字符串
QByteArray data = doc.toJson();
第四步——将字符串写入文件
// 字符串写入文件
QFile file("D:\\temp.json");
file.open(QIODevice::WriteOnly);
file.write(data);
file.close();
整体
// 创建json对象
QJsonObject obj;
//创建子对象
QJsonObject sub;
sub.insert("IP", QJsonValue("192.168.1.25"));
sub.insert("port", "9990");
//将子对象作为value放在json对象中
obj.insert("server", QJsonValue(sub));
// 内存中的json数据写入内存
//构造json对象
QJsonDocument doc(obj);
// 将json对象转换为字符串
QByteArray data = doc.toJson();
// 字符串写入文件
QFile file("D:\\temp.json");
file.open(QIODevice::WriteOnly);
file.write(data);
file.close();
例子——使用json类读json文件
// 读json文件
QFile file("D:\\temp.json");
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
file.close();
// 使用jsonDocument对象加载json字符串
QJsonDocument doc = QJsonDocument::fromJson(data);
// 判断文件中是json数组还是json对象。是对象,则需要进行解析
if(doc.isObject())
{
QJsonObject obj = doc.object();
//通过key值将value取出
QJsonValue value = obj.value("server");
//如果取出来的值还是一个对象,则继续取值
if(value.isObject())
{
QJsonObject subobj = value.toObject();
// 通过key来取值。因为我们知道是字符串,所以这里没有判断取出来的是否是字符串
QString ip = subobj.value("IP").toString();
QString port = subobj.value("port").toString();
//打印取出来的结果
qDebug() << ip << port;
}
}
项目中先关的配置文件信息
1、服务器端配置文件
{
"redis":
{
"ip": "127.0.0.1",
"port": "6379"
},
"mysql":
{
"ip": "127.0.0.1",
"port": "3306",
"database": "cloud_disk",
"user": "root",
"password": "root"
},
"dfs_path":
{
"client": "./conf/client.conf"
},
"web_server":
{
"ip": "192.168.82.251",
"port": "80"
},
"storage_web_server":
{
"ip": "192.168.82.251",
"port": "80"
}
}
2、客户端
{
"login": {
"pwd": "wqq2b4Ild/w=",
"remember": "yes",
"user": "Mi/CvL0kLkQ="
},
"type_path": {
"path": "conf/fileType"
},
"web_server": {
"ip": "192.168.1.27",
"port": "80"
}
}
Qt中使用http协议通信
C/S架构的进行网络通信时,可选协议很多。本项目选择http请求,这样可以支持客户端和网页端两种方式来获取服务器数据 。
QNetworkAccessManager类允许应用程序发送网络请求和接收网络应答。
Network Access API都是围绕着一个QNetworkAccessManager对象构造的,这个对象包含着发送请求的一些通用配置和设置。它包含着代理和缓存的配置,以及和这些事物相关的一些信号,并且应答信号可以作为我们检测一个网络操作的进度。
一个QNetworkAccessManager对于一整个Qt应用程序来说已经足够了!
一旦一个QNetworkAccessManager对象被创建了,那么应用程序就可以使用它在网络上发送请求。它提供了一组标准的函数,可以承载网络请求和一些可选的数据,并且每一个请求返回一个QNetworkReply对象。该返回的对象包含着返回的请求应带的所有数据。
头文件
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
QNetworkAccessManager 类——发送get请求或者post请求
- QNetworkAccessManager将会把它受到的请求排队。并行执行的请求数量是依赖于协议的。
- 目前,对于桌面平台的HTTP协议,对于一个主机/端口的组合,可6个请求并行执行。
QNetworkRequest类——组织请求头
- Network Access API的一部分,并且这个类包含着在网络上发送请求的必要信息。
- 它包含了一个URL和一些可以用来修改请求的附加信息。
- 将需要发送的http请求协议初始化到QNetworkRequest类中,包括——请求头、数据、url
QNetworkReply 类——处理回复
- QNetworkAccessManage返回的一个对象, 请求完成之后, 需要删除该对象
- 我们通过QNetworkAccessManage返回的对象, 读server返回的数据
readyRead()
finished();
readall()
例子
发送get请求访问www.baidu.com:80、获取服务器返回的数据、读取数据并将数据打印
// 需要一个mamager对象, 做get ,post。一个项目里面有一个QNetworkAccessManager即可
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
// 准备工作 - 初始化一个QNetworkRequest
QNetworkRequest res;
// 设置头 - 浏览器
res.setHeader(QNetworkRequest::UserAgentHeader,
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36");
//要发送给谁
res.setUrl(QUrl("http://www.baidu.com:80"));
//获取服务器返回的数据
QNetworkReply* reply = manager->get(res);
// 读服务器回写的数据
connect(reply, &QNetworkReply::readyRead, this, [=]()
{
// 获取返回的头,查看是否是302(重定向)
QVariant str = reply->header(QNetworkRequest::LocationHeader);
// 读取所有数据,不包括头
QByteArray data = reply->readAll();
qDebug() << data;
qDebug() << str.toString();
});
项目中需要用到的mysql表
数据库基本操作语句
1、创建一个名称为cloud_disk的数据库。
CREATE DATABASE cloud_disk;
2. 删除数据库cloud_disk
drop database cloud_disk;
3. 使用数据库 cloud_disk
use cloud_disk;
用户信息表 - user表
1、用户信息表字段:
id |
用户序号,自动递增,主键 |
name |
用户名字 |
nickname |
用户昵称 |
phone |
手机号码 |
|
邮箱 |
password |
密码 |
createtime |
时间 |
2、sql语句 - 建表
CREATE TABLE user (
id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR (128) NOT NULL,
nickname VARCHAR (128) NOT NULL,
password VARCHAR (128) NOT NULL,
phone VARCHAR (15) NOT NULL,
createtime VARCHAR (128),
email VARCHAR (100),
CONSTRAINT uq_nickname UNIQUE (nickname), #指定nickname是唯一的
CONSTRAINT uq_name UNIQUE (NAME) #指定name是唯一的
);
3、sql语句 - 插入
INSERT INTO USER (name, nickname, password, phone, createtime, email)
VALUES('mike', 'sb', '123456','110','2017-01-11 17:47:30','[email protected]');
4、sql语句 - 查询
SELEC id FROM user WHERE name = "kevin";
文件信息表 - file_info表
1、文件信息表字段
md5 |
文件md5 |
file_id |
文件id-/group1/M00/00/00/xxx.png |
url |
文件url 192.168.1.2:80/group1/M00/00/00/xxx.png |
size |
文件大小, 以字节为单位 |
type |
文件类型: png, zip, mp4…… |
count |
文件引用计数, 默认为1 每增加一个用户拥有此文件,此计数器+1 |
补充:
md5是文件上传到云盘之后,我们会生成一个md5的哈希值,md5不论文件多大,算出来的字符串长度相同。每个文件对应一个md5.
文件秒上传也是通过md5,。上传文件时,计算其md5,如果md5存在,说明storage中存有该文件,则无需上传。
2、sql语句 - 建表
CREATE TABLE file_info (
md5 VARCHAR (200) NOT NULL PRIMARY KEY,
file_id VARCHAR (256) NOT NULL,
url VARCHAR (512) NOT NULL,
size BIGINT,
type VARCHAR (20),
count INT
);
3、sql语句 - 更新
UPDATE file_info SET count = 2 WHERE md5 = "bae488ee63cef72efb6a3f1f311b3743";
用户文件列表 - user_file_list表
1、用户文件列表字段
user |
文件所属用户 |
md5 |
文件md5 |
createtime |
文件创建时间 |
filename |
文件名字 |
shared_status |
共享状态, 0为没有共享, 1为共享 |
pv |
文件下载量,默认值为0,下载一次加1 |
2、sql语句 - 建表
CREATE TABLE user_file_list (
user VARCHAR (128) NOT NULL,
md5 VARCHAR (200) NOT NULL,
createtime VARCHAR (128),
filename VARCHAR (128),
shared_status INT,
pv INT
);
3、查看某个用户的文件列表
SELECT md5 FROM user_file_list WHERE name = "mike";
4、查看某个文件的属性
SELECT * FROM file_info WHERE md5 = "bae488ee63cef72efb6a3f1f311b3743";
5、设置某个文件是否共享
UPDATE user_file_list SET shared_status = 1 WHERE md5 = "bae488ee63cef72efb6a3f1f311b3743" AND user = 'mike';
用户文件数量表 - user_file_count表
1、用户文件数量表字段
user |
文件所属用户 |
count |
拥有文件的数量 |
2、sql语句 - 建表
CREATE TABLE user_file_count (
user VARCHAR (128) NOT NULL PRIMARY KEY,
count INT
);
3、更新
UPDATE user_file_count SET count = 10 WHERE user = "mike";
4、删除
DELETE FROM user_file_count WHERE user = "mike";
共享文件列表
1、共享文件列表字段
user |
文件所属用户 |
md5 |
文件md5 |
createtime |
文件共享时间 |
filename |
文件名字 |
pv |
文件下载量,默认值为1,下载一次加1 |
2、建表
CREATE TABLE share_file_list (
user VARCHAR (128) NOT NULL,
md5 VARCHAR (200) NOT NULL,
createtime VARCHAR (128),
filename VARCHAR (128),
pv INT
);
md5——文件的指纹
Message-Digest Algorithm 5(信息-摘要算法5)
MD5算法具有以下特点:
压缩性:
- 任意长度的数据,算出的MD5值长度都是固定的。
- 把一个任意长度的字节串变换成一定长的十六进制数字串
容易计算:
- 从原数据计算出MD5值很容易。
抗修改性
- 对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
强抗碰撞:
- md5过程是不可逆的
- 已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
md5的应用
- 文件校验——软件下载站、论坛数据库、系统文件安全等方面
- 数字证书——互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在Internet上验证通信实体身份的方式
- 登录验证——操作系统的登陆认证,如Unix、各类BSD系统登录密码
Qt中md5的使用
需要依靠类——QCryptographicHash
头文件
#include <QCryptographicHash>
实现代码
// 获取文件数据(这里先用字符串代替)
QByteArray data = "hello, world";
//构造md5对象
QCryptographicHash hash(QCryptographicHash::Md5);
//添加数据
hash.addData(data);
//可以继续添加数据
hash.addData("你好, 世界");
// 计算
QByteArray arry = hash.result();
qDebug() << arry;
//转成16进制。因为md5是由16进制数字组成,不转换,则输出的是字符
arry = arry.toHex();
qDebug() << arry;
另一种转化md5的方式
QByteArray arry = QCryptographicHash::hash("hello, world", QCryptographicHash::Md5);
qDebug() << arry.toHex();
补充:文件内容相同,如果编码方式不同,则md5不同
base64算法
Base64是一种用64个字符来表示任意二进制数据的方法。
1、为什么要用base64编码
- 在网络上交换数据时,比如说从A地传到B地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。
- 把数据先做一个Base64编码,统统变成可见字符,这样出错的可能性就大降低了
- 很多场景下的数据传输要求数据只能由简单通用的字符组成,比如HTTP协议要求请求的首行和请求头都必须是ASCII编码
2、使用base64能做什么
- 所有的二进制文件,都可以因此转化为可打印的文本编码,使用文本软件进行编辑
- 能够对文本进行简单的加密
3、算法描述
- 将字符串分隔成3个字节为一组,每组八位的几组小串
- 把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24)
- 在6位的前面补两个0,形成8位一个字节的形式
- 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'=', 表示补了多少字节,解码的时候,会自动去掉。
Qt中使用base64
需要用到类——QByteArray
实现代码
// 编码
QByteArray base = "你好, 世界";
base = base.toBase64();
qDebug() << base;
// 解码
base= QByteArray::fromBase64(base);
qDebug() << base.data();