【云备份】第三方库的认识与使用
文章目录
- json库
- 粗略认识
- 详细认识
- writer 类
- reader类
- jsoncpp序列化实现
- jsoncpp反序列化实现
- bundle文件压缩库
- 简单认识
- bundle库实现文件压缩
- bundle库实现文件解压缩
- httplib库
- Request类
- Response类
- Server类
- Client类
json库
粗略认识
json是一种数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据
![](https://img-blog.csdnimg.cn/ffea7273ed4740cfbf53baca3c8c0bb2.png)
姓名是char类型、年龄是 int类型、 成绩是 float类型
json将多种数据类型对象 组织成为一个字符串
json数据类型:对象、数组、字符串、数字
对象:使用 {} 括起来的表示一个对象
如:小明 和小黑 两个 学生信息对象
数组:使用 [] 括起来的表示一个数组
如:小明和小黑的成绩都有三个数,用[] 括起来 表示一个数组
字符串:使用" "括起来的表示一个字符串
如:小明和小黑的名字 使用双引号,表示字符串
数字:包括整形和浮点型 直接使用
如:小明和小黑的年龄 可以直接 填入 即可
详细认识
jsoncpp库 用于实现 json格式 的序列化和反序列化,完成将多个数据对象组织成为 json格式字符串
以及将json格式字符串 解析得到多个数据对象的功能
主要借助三个类以及对应的成员函数完成:
![](https://img-blog.csdnimg.cn/007d98d882c3401d83508f78bac420a6.png)
该类中重载了 [] 和 = 两个运算符
好处是 进行数据存储时,json::value类会保存所有的数据对象
也可以用 asString 寻找对应数据中属于string的部分
用 asInt 寻找对应数据中属于int的部分
writer 类
将json::value 对象中所保存的多个数据对象的数据 进行序列化
![](https://img-blog.csdnimg.cn/f90b11c114bc42aca0547604f30f1935.png)
json_api writer json_api fastwriter 、 json_api styledwriter 作为低版本
使用低版本,可能会报警告
![](https://img-blog.csdnimg.cn/cbe87b76f3414bbdbddfa01359baddba.png)
json_api streamwriter json_api streanwriterbuilder 作为高版本
使用高版本,则不会有警告
无论低版本还是高版本 都有 write 这个成员函数
传递一个 json::value的数据对象,将这个对象中的所有的数据 按照 json格式 进行序列化
若为低版本,则直接返回一个 json数据串
若为高版本,则 将json 数据串 放入 流中
reader类
![](https://img-blog.csdnimg.cn/b2aadee0b0b249af9819495acc86d7f3.png)
实现 json的反序列化
即 将json格式的字符串 反序列化 解析得到多个数据对象,放入 json::value 对象中
![](https://img-blog.csdnimg.cn/4ba11fe0e8f844cda821c45455ba1687.png)
反序列化的低版本 为 json_api reader
使用其中的 parse接口, 第一个参数 decument 作用为 json格式的字符串 传入
第二个参数root 作用为 将反序列化得到的对象存放到 root中
![](https://img-blog.csdnimg.cn/fdb0ddf7a15f4f2aa47fc0bfa1ac7888.png)
反序列化的高版本 共有两种 charreader 和 charreaderbuilder
先通过 charreaderbuilder 类中的 newcharreader接口 实例化一个 charreader 对象
再去通过 调用charreader 类中的 parse 接口
第一个参数为 字符串的起始地址 第二个参数为字符串的结束地址
第三个参数为 json::value对象的指针
将字符串内容进行反序列化 放入 root中
若解析出错,则会把错误信息 放入 第四个参数 errs中
jsoncpp序列化实现
![](https://img-blog.csdnimg.cn/ce267e08b79c4c94ae3fa36c4fab77aa.png)
假设有以上信息
1.需要先将数据保存到 json::value 对象中
![](https://img-blog.csdnimg.cn/4a8d3e90ea8742b180b102b8dd895424.png)
2.想要使用 json::StreamWriter 进行序列化 ,就需要先借助 json::StreamWriterBuilder 实例化一个 StreamWriter对象
然后再使用 StreamWriter类中的 write接口 ,将数据串 放入流中
![](https://img-blog.csdnimg.cn/0ca02055319a4a1b9fc906a94aec996c.png)
将上述信息放入主函数main中
![](https://img-blog.csdnimg.cn/e272a92a62c04d5594a8bbaac87263bc.png)
在实例化一个 json::value类型的root对象,将上面的的数据保存到root中
因为 json::value 重载了运算符,所以基础数据是可以直接通过赋值来完成的
![](https://img-blog.csdnimg.cn/3bd9ed14bb5d4b929cab458653c86dd9.png)
实例化一个 StreamWriterBuilder类型的对象 swb
再通过类中的newStreamWriter接口 实例化一个StreamWriter对象被命名为 sw
![](https://img-blog.csdnimg.cn/e3351f9452de4723bb3d05fff19716aa.png)
定义一个 stringstream 流 ss
在借助StreamWriter类中的 write接口,将root中的数据串 传入 流中
最后打印流中的数据
![](https://img-blog.csdnimg.cn/c7889dd536cd467e98668ff4ef4f3fc8.png)
![](https://img-blog.csdnimg.cn/9df047ac915e445b873029b0f9603a8b.png)
输入 g++ json_example.cpp -o json_example -ljsoncpp
再次执行程序 , 将数据串 显示到流中
jsoncpp反序列化实现
string str= “{“姓名”:“小黑”,“年龄”:19,“成绩”:[58.5,66,35.5]}”;
{外的双引号 与 {内的双引号 有歧义 ,就需要用 \ 进行转义 ,表示用的是 原始的双引号
string str=R"({“姓名”:“小黑”,“年龄”:19,“成绩”:[58.5,66,35.5]})“;
若想简单写,则可以使用C++11中的特殊用法 R”( )" 表示括号内部都是原始字符串,所有的字符都已经去除了特殊含义
jsoncpp中进行反序列化 ,是将字符串中的数据解析放到了 Json::Value 中
1.定义一个Json::Value对象 root
![](https://img-blog.csdnimg.cn/c50db6f1d7fa40c9a766f9af26383268.png)
2. 想要使用 CharReader 进行反序列化 ,则需要先通过 CharReaderBuilder 实例化一个对象 CharReader
在调用 CharReader 的 parse接口
![](https://img-blog.csdnimg.cn/9771d20c9e974dc88d10903a2b2cbf89.png)
创建一个str字符串,并且内部都是原始字符串
![](https://img-blog.csdnimg.cn/31b6b75894f74823baa8e40285c6003c.png)
![](https://img-blog.csdnimg.cn/fc896c00e74d4559bbe565cc20c235ff.png)
创建一个 json::value 类型的root对象
实例化一个 json::CharReaderBuilder类型的对象 crb
再通过类中的 newCharReader接口 实例化一个CharReader 对象被命名为 cr
![](https://img-blog.csdnimg.cn/1274d62bf1574777bb989139f21d15ad.png)
若ret为false,则说明反序列化失败
若ret为true, 则说明反序列化成功
root[“姓名”].asString() 表示 获取到 姓名对应数据中的string数据
所以使用 asString 表示 获取对应的string数据
root[“年龄”].asInt() 表示 获取到 年龄对应数据中的int数据
所以使用 asInt 表示 获取对应的int数据
![](https://img-blog.csdnimg.cn/97c655110c54406393421d00aba2ee59.png)
![](https://img-blog.csdnimg.cn/bc0cc79e7b984d54aa193b1a6de41011.png)
反序列化后,数据全部放入root中,最终 将root对象中的数据全部打印出来
bundle文件压缩库
简单认识
bundleBundle 是一个嵌入式压缩库,使用时只需要加入两个文件 bundle.h 和 bundle.cpp 即可
bundle库实现文件压缩
由于在之前已经安装过了 bundle库,所以直接使用 bundle-master
![](https://img-blog.csdnimg.cn/409bdcff433a485c8936c58c4fc3fbd7.png)
将 bundle-master 中的 bundle.cpp 和 bundle.h 拷贝出来 当到当前目录中
![](https://img-blog.csdnimg.cn/6e4807637e804f2390c4a374bc8bc683.png)
从运行参数中获取到文件压缩的文件名和压缩包名称
打开原文件,读取对应的数据,再对其进行压缩
共有三个参数,文件压缩 文件名和压缩包名称
如果agv小于3,则表示参数个数不够,则直接返回-1
![](https://img-blog.csdnimg.cn/d2bc4bdc3ce24e51b38bfe5b28320c1d.png)
iffilename表示文件名称
offilename表示压缩包的名称
![](https://img-blog.csdnimg.cn/e766d35d37a143c9b6cc441d0f72314e.png)
使用ifstream文件流 创建变量ifs
open打开原始文件,打开的是输入文件
输入 ios::binary i以二进制形式打开文件
iseekg i 作用为跳转到读写位置到末尾
![](https://img-blog.csdnimg.cn/462305d0d13143019cbff2ec240a7aef.png)
获取末尾偏移量 即文件长度
![](https://img-blog.csdnimg.cn/b709e1ce301c49859353105a6408bed4.png)
跳转到文件起始位置
![](https://img-blog.csdnimg.cn/a45fd7ebf1c940d18bff9ab5a977beb2.png)
创建一个字符串 body
调整body大小为文件大小
读取文件所有数据到 body中
![](https://img-blog.csdnimg.cn/5c2d762970a74e689c73d22bda25ab3c.png)
选择 LZIP 压缩格式,body作为文件内容,使用 pack 进行压缩,返回值就是压缩之后的数据
![](https://img-blog.csdnimg.cn/1a7d7336ff9c434f80f9ffb1145b22e6.png)
以输出文件流 ofstream 创建变量 ofs
以二进制的方式打开压缩包 文件
将压缩后的数据写入 压缩包文件中
![](https://img-blog.csdnimg.cn/add3bfb21cb8496c9260e801ea1289cd.png)
![](https://img-blog.csdnimg.cn/2844ff55115a440da1aa7c5a2b5cdad0.png)
![](https://img-blog.csdnimg.cn/16b9d9bf692c4069bc5904ef24ee7438.png)
执行compress可执行程序 即可运行出来
![](https://img-blog.csdnimg.cn/f3930a79505b46438d091966522b128f.png)
bundle.cpp文件大小为5.4M
通过compress 将其 进行压缩成 bundle.cpp.lz
再次查看发现bundle.cpp.lz大小为668K
bundle库实现文件解压缩
将文件压缩后的 bundle.cpp.lz 进行解压 , 再将解压的文件与 bundle.cpp进行对比
![](https://img-blog.csdnimg.cn/2d779ee2a9b9448997bd7cc08e976ab5.png)
共有三个参数,文件压缩 压缩包名称和文件名称
如果agv小于3,则表示参数个数不够,则直接返回-1
![](https://img-blog.csdnimg.cn/cd87a67a6e474e3191551103bd36ec2b.png)
以 istream文件流 创建变量 ifs
将filename文件 以二进制形式打开
使用 seekg 使 ifs 处于文件末尾
再通过 tellg 获取文件大小
最终通过 beg 跳转到 ifs文件的起始位置
![](https://img-blog.csdnimg.cn/ebce5acc0c1a4ea8a74317e35b49df55.png)
创建一个字符串 body
调整body大小为文件大小
读取ifs文件所有数据到 body中
![](https://img-blog.csdnimg.cn/919b69533fcc461b8db96a5c2f254f0a.png)
通过 bundle 库中的 unpack 进行解压缩
![](https://img-blog.csdnimg.cn/5ea2d0c6654a4abdb7a3732a91fe150b.png)
以 输出文件流ofstram 创建变量 ofs
以二进制形式,将ofilename文件打开
将解压缩后的数据 全部放入 ofs文件 中
![](https://img-blog.csdnimg.cn/af2c6d77edf2431c9040359f68dca3c8.png)
![](https://img-blog.csdnimg.cn/3b2e20e92daa48f5bff04093869e2232.png)
httplib库
httplib库 是一个c++11单文件头的跨平台 HTTP/HTTPS库
只需包含 httplib.h 在代码中即可
实际用于搭建一个简单的http服务器或者客户端的库,这种第三方库免去搭建服务器或客户端的时间,提高开发效率
Request类
![](https://img-blog.csdnimg.cn/54ef922a4fc2464986274480ba226455.png)
HTTP
首行: 请求方法 URL 协议版本
头部:key 与value 形成的KV模型
空行:\r\n
正文:提交给服务器的数据
请求方法中包含 GET获取资源 以及 POST提交表单数据
Request结构体的作用:
1.客户端保存的所有http请求相关信息,最终组织http请求发送给服务器
2.服务器收到http请求之后进行解析,将解析的数据保存在request结构体中,等待后续处理
![](https://img-blog.csdnimg.cn/a13537c86764482f955cce8cd1e5ddaa.png)
![](https://img-blog.csdnimg.cn/a34157dd6f4840bf9bd467b06a25bbe3.png)
MultipartFormDataMap 内部包含四个字段
name为字段名称
content为文件内容
filename为文件名称
coneent_type 为正文类型
![](https://img-blog.csdnimg.cn/7445a2a79fa040fea10b62e2d908f743.png)
has_header 查询头部字段
get_heaer_value 获取头部字段的值
set_header 设置头部字段的值
has_file 是否包含某个文件
get_file_value 获取文件信息
Response类
![](https://img-blog.csdnimg.cn/e24dfb75bf0d463fa1bc1879b45d72a5.png)
HTTP响应格式
首行:协议版本 响应状态码 状态码描述
头部:响应的关键性描述字段 key: value\r\n key:value\r\n
空行: \r\n
正文:响应给客户端的数据
Response结构体功能
用户将响应数据放到结构体中,httplib会将其中的数据按照http响应格式 组织成为http
Server类
Server功能
用于搭建http服务器
![](https://img-blog.csdnimg.cn/7d01036704654e49af546932acd7a213.png)
listen作为搭建服务器并启动http服务器
![](https://img-blog.csdnimg.cn/3fe9c19a37fc449b8dcc26cfd07ce395.png)
handler是一个函数指针类型的业务处理函数,定义了一个http请求处理回调函数格式
第一个参数 request 为 保存请求数据,让用户能够根据请求数据进行业务处理
第二个参数 response 为 用户在业务处理中,填充数据,最终要响应给客户端
http搭建的服务器收到请求后,进行解析,得到一个Request结构体,其中包含请求数据
根据请求数据 就可以将请求处理,处理函数定义的格式为Handler格式
![](https://img-blog.csdnimg.cn/1c530e0c47c54365b89c23e27aa82467.png)
Handlers是 请求与处理函数映射表
为一个请求路由数组,数组中包含两个信息
regex 为 正则表达式 用于匹配 http请求资源路径
Handler 为 请求处理函数指针
可以将 Handlers 看作一张表 映射了客户端请求的资源路径和一个处理函数(用户自己定义的函数)
当服务器收到请求解析得到 Request 就会根据 资源路径以及请求方法到这张表中查看有没有对应的处理函数
如果有则调用这个函数进行请求处理
如果没有则响应404
![](https://img-blog.csdnimg.cn/c78b66dbe087405d8d9b552bac3415a4.png)
new_task_queue 作为一个线程池 用于处理请求
httplib 会收到一个新建 连接,则将新的客户端连接抛入 线程池中
线程池中线程的工作:
1.接收请求,解析请求,得到request结构体 即请求数据
2.在Handlers映射表中,根据请求信息 查找处理函数,如果有则调用函数处理,如果没有则响应404
3.当处理函数调用完毕后,根据函数返回的response结构体中的数据 组织 http响应 发送给客户端
Client类
![](https://img-blog.csdnimg.cn/cb46fa4b1ac14dc2855f19a74b27def7.png)
Client类 用于搭建 http的客户端
GET 向服务器发送GET请求
传入的是 请求的资源路径和 头部字段
第一个POST 发送post请求
path为资源路径、body作为正文数据、length作为正文长度、content_type 作为 正文类型
第二个POST POST请求提交多区域数据 常用于多文件上传
path为资源路径
MultipartFormDataItems 是一个数组,而items 为上传的文件信息