C++项目——云备份-②-第三方库认识

news2024/11/19 4:42:08

文章目录

  • 专栏导读
  • 1. json 认识
    • 1.1 JSON 数据结构的特点
  • 2. jsoncpp库认识
  • 3. json实现序列化案例
  • 4. json实现反序列化案例
  • 5. bundle文件压缩库认识
  • 6. bundle库实现文件压缩案例
  • 7.bundle库实现文件解压缩案例
  • 8.httplib库认识
  • 9. httplib库搭建简单服务器案例
  • 10. httplib库搭建简单客户端案例

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——云备份

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux
🌸项目Gitee链接:https://gitee.com/li-yuanjiu/cloud-backup

在这里插入图片描述

1. json 认识

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,用于在不同应用程序之间传递和存储数据。它的设计目标是易于阅读和编写,同时也易于解析和生成。JSON采用文本格式,通常以.json文件扩展名存储,以及一种键-值对的结构,其中数据以一种易于理解的方式表示,适合机器和人类阅读。

1.1 JSON 数据结构的特点

  • 键-值对:JSON 数据由键-值对组成,键和值之间使用冒号分隔,键-值对之间使用逗号分隔。键通常是字符串,值可以是字符串数字布尔值数组对象null等。
{
    "name": "小明",
    "age": 30,
    "isStudent": true
}
  • 对象:对象是一种包含键-值对的数据结构,用大括号{}表示。对象的键是唯一的
{
    "person": {
        "name": "Alice",
        "age": 25
    }
}
  • 数组:数组是一种有序的值的集合,用方括号[]表示。数组可以包含各种数据类型,包括对象和其他数组。
{
    "fruits": ["apple", "banana", "orange"]
}
  • 字符串:字符串是以双引号""括起来的文本。字符串可以包含任何字符,包括特殊字符和转义序列。
{
    "message": "Hello, World!"
}
  • 数字:数字可以是整数或浮点数,不需要引号包围。
{
    "price": 19.99
}
  • 布尔值:表示真或假的值,可以是truefalse
{
    "isSunny": true
}
  • null:表示空值或缺失值。
{
    "data": null
}

2. jsoncpp库认识

jsoncpp 库用于实现 json 格式的序列化和反序列化,完成将多个数据对象组织成为 json 格式字符串,以及将 json 格式字符串解析得到多个数据对象的功能。

这其中主要借助三个类以及其对应的少量成员函数完成:

json数据对象类

//Json数据对象类
class Json::Value{
  Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取数据都可以通过
  Value& operator[](const std::string& key);//简单的方式完成 val["姓名"] = "小明";
  Value& operator[](const char* key);
  Value removeMember(const char* key);//移除元素
  const Value& operator[](ArrayIndex index) const; //val["成绩"][0]
  Value& append(const Value& value);//添加数组元素val["成绩"].append(88);
  ArrayIndex size() const;//获取数组元素个数 val["成绩"].size();
  std::string asString() const;//转string string name = val["name"].asString();
  const char* asCString() const;//转char*  char *name = val["name"].asCString();
  Int asInt() const;//转int int age = val["age"].asInt();
  float asFloat() const;//转float
  bool asBool() const;//转 bool
};

json序列化类

//json序列化类,低版本用这个更简单
class JSON_API Writer {
 virtual std::string write(const Value& root) = 0;
}
class JSON_API FastWriter : public Writer {
virtual std::string write(const Value& root);
}
class JSON_API StyledWriter : public Writer {
 virtual std::string write(const Value& root);
}
//json序列化类,高版本推荐,如果用低版本的接口可能会有警告
class JSON_API StreamWriter {
  virtual int write(Value const& root, std::ostream* sout) = 0;
}
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
  virtual StreamWriter* newStreamWriter() const;
}

json反序列化类

//json反序列化类,低版本用起来更简单
class JSON_API Reader {
bool parse(const std::string& document, Value& root, bool collectComments = true);
}
//json反序列化类,高版本更推荐
class JSON_API CharReader {
  virtual bool parse(char const* beginDoc, char const* endDoc,
           Value* root, std::string* errs) = 0;
}
class JSON_API CharReaderBuilder : public CharReader::Factory {
  virtual CharReader* newCharReader() const;
}

3. json实现序列化案例

/*
    json 序列化
*/
#include <iostream>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>

int main()
{
    const char* name = "小明";
    int age  = 18;
    float score[] = {77.5, 88, 93.6}; // 语数英成绩

    Json::Value root; // 定义一个Value对象
    root["name"] = name;
    root["age"] = age;
    root["成绩"].append(score[0]); // 在数组中插入数据用append函数
    root["成绩"].append(score[1]);
    root["成绩"].append(score[2]);
    
    // std::cout << root << std::endl;
    Json::StreamWriterBuilder swb;
    std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
    std::stringstream ss;
    sw->write(root, &ss);
    std::cout << ss.str() << std::endl;

    return 0;
}
$ g++ -o json_example json_example.cpp -ljsoncpp
$ ./json_example

运行结果
在这里插入图片描述

4. json实现反序列化案例

/*
    json 反序列化
*/
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>

int main()
{
    std::string str = R"({"姓名":"小黑", "年龄":19, "成绩":[58.5, 44, 20]})";
    Json::Value root;
    Json::CharReaderBuilder crb;
    std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
    std::string err;
    bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
    if(ret == false)
    {
        std::cout << "parse error: " << err << std::endl;
        return -1; 
    }

    std::cout << root["姓名"].asString() << std::endl;
    std::cout << root["年龄"].asInt() << std::endl;
    int sz = root["成绩"].size();
    for(int i = 0; i < sz; i++)
    {
        std::cout << root["成绩"][i] << std::endl; 
    }

    return 0;
}
$ g++ -o json_example2 json_example2.cpp -ljsoncpp
$ ./json_example2

运行结果

在这里插入图片描述

5. bundle文件压缩库认识

Bundle 是一个嵌入式压缩库,支持23种压缩算法和2种存档格式。使用的时候只需要加入两个文件 bundle.hbundle.cpp 即可。

以下是常用接口:

namespace bundle
{
 // low level API (raw pointers)
 bool is_packed( *ptr, len );
 bool is_unpacked( *ptr, len );
 unsigned type_of( *ptr, len );
 size_t len( *ptr, len );
 size_t zlen( *ptr, len );
 const void *zptr( *ptr, len );
 bool pack( unsigned Q, *in, len, *out, &zlen );
 bool unpack( unsigned Q, *in, len, *out, &zlen );
 // medium level API, templates (in-place)
 bool is_packed( T );
 bool is_unpacked( T );
 unsigned type_of( T );
 size_t len( T );
 size_t zlen( T );
 const void *zptr( T );
 bool unpack( T &, T );
 bool pack( unsigned Q, T &, T );
 // high level API, templates (copy)
 T pack( unsigned Q, T );
 T unpack( T );
}

6. bundle库实现文件压缩案例

#include <iostream>
#include <fstream>
#include <string>
#include "bundle.h"

int main(int argc, char* argv[])
{
    std::cout << "argv[1] 是原始文件路径名称\n";
    std::cout << "argv[2] 是压缩包名称\n";
    if(argc < 3) return -1;

    std::string ifilename = argv[1];
    std::string ofilename = argv[2];

    std::ifstream ifs;
    ifs.open(ifilename, std::ios::binary); // 打开原始文件
    ifs.seekg(0, std::ios::end); // 跳转读写位置到末尾
    size_t fsize = ifs.tellg(); // 获取末尾偏移量--文件长度
    ifs.seekg(0, std::ios::beg); // 跳转到文件起始
    std::string body;
    body.resize(fsize); // 调整body大小为文件大小
    ifs.read(&body[0], fsize); // 读取文件所有数据到body

    std::string packed = bundle::pack(bundle::LZIP, body); // 以lzip格式压缩文件数据

    std::ofstream ofs;
    ofs.open(ofilename, std::ios::binary); // 打开压缩包文件
    ofs.write(&packed[0], packed.size()); // 将压缩后的数据写入压缩包文件

    ifs.close();
    ofs.close();

    return 0;
}
$ g++ -o compress compress.cpp bundle.cpp -lpthread
$ ./compress bundle.cpp bundle.cpp.lz

运行结果

在这里插入图片描述

7.bundle库实现文件解压缩案例

#include <iostream>
#include <fstream>
#include <string>
#include "bundle.h"

int main(int argc, char* argv[])
{
  if(argc < 3)
  {
    printf("argv[1]是压缩包名称\n");
    printf("argv[2]是解压缩后的文件\n");
    return -1;
  }
  std::string ifilename = argv[1]; // 压缩包名
  std::string ofilename = argv[2]; // 解压缩后文件名

  std::ifstream ifs;
  ifs.open(ifilename, std::ios::binary); // 打开压缩文件
  ifs.seekg(0, std::ios::end); // 跳转到读写位置到文件末尾
  size_t fsize = ifs.tellg(); // 获取末尾偏移量--获取文件长度
  ifs.seekg(0, std::ios::beg); // 返回到文件起始
  std::string body;
  body.resize(fsize); // 调整body大小为文件大小
  ifs.read(&body[0], fsize); // 读取压缩文件所有内容到body
  ifs.close();

  std::string unpacked = bundle::unpack(body); // 进行解压缩,将解压缩后的数据保存到unpack中
  std::ofstream ofs;
  ofs.open(ofilename, std::ios::binary); // 打开文件
  ofs.write(&unpacked[0], unpacked.size()); // 将解压缩后的数据写入文件
  ofs.close();
  return 0;
}
$ g++ -o uncompress uncompress.cpp bundle.cpp -lpthread
$ ./uncompress bundle.cpp.lz bundle.tmp
$ 计算两个文件的md5值,看是否完全相同
$ md5 bundle.cpp
$ md5sum bundle.tmp

运行结果

在这里插入图片描述

8.httplib库认识

httplib 库,一个 C++11 单文件头的跨平台 HTTP/HTTPS 库。安装起来非常容易。只需包含 httplib.h 在你的代码中即可。

httplib 库实际上是用于搭建一个简单的 http 服务器或者客户端的库,这种第三方网络库,可以让我们免去搭建服务器或客户端的时间,把更多的精力投入到具体的业务处理中,提高开发效率。

常用接口如下:

namespace httplib{
  struct MultipartFormData {
    std::string name;
    std::string content;
    std::string filename;
    std::string content_type;
 };
  using MultipartFormDataItems = std::vector<MultipartFormData>;
  struct Request {
    std::string method;
    std::string path;
    Headers headers;
    std::string body;
    // for server
    std::string version;
    Params params;
    MultipartFormDataMap files;
    Ranges ranges;
    bool has_header(const char *key) const;
    std::string get_header_value(const char *key, size_t id = 0) const;
    void set_header(const char *key, const char *val);
    bool has_file(const char *key) const;
    MultipartFormData get_file_value(const char *key) const;
 };
  struct Response {
    std::string version;
    int status = -1;
    std::string reason;
    Headers headers;
    std::string body;
    std::string location; // Redirect location
	void set_header(const char *key, const char *val);
    void set_content(const std::string &s, const char *content_type);
 };
class Server {
    using Handler = std::function<void(const Request &, Response &)>;
    using Handlers = std::vector<std::pair<std::regex, Handler>>;
    std::function<TaskQueue *(void)> new_task_queue;
    Server &Get(const std::string &pattern, Handler handler);
Server &Post(const std::string &pattern, Handler handler);
    Server &Put(const std::string &pattern, Handler handler);
Server &Patch(const std::string &pattern, Handler handler); 
Server &Delete(const std::string &pattern, Handler handler);
Server &Options(const std::string &pattern, Handler handler);
    bool listen(const char *host, int port, int socket_flags = 0);
};
class Client {
    Client(const std::string &host, int port);
	Result Get(const char *path, const Headers &headers);
    Result Post(const char *path, const char *body, size_t content_length,
       const char *content_type);
    Result Post(const char *path, const MultipartFormDataItems &items);
 }
}

9. httplib库搭建简单服务器案例

#include <iostream>
#include "httplib.h"
using namespace httplib;
void Hello(const Request &req, Response &rsp)
{   
    rsp.set_content("Hello World!", "text/plain");
    rsp.status = 200; // 设置状态码
}
void Numbers(const Request &req, Response &rsp)
{   
    auto num = req.matches[1]; // 0里边保存的是整体path,往后下标中保存的是捕捉的数据
    rsp.set_content(num, "text/plain");
    rsp.status = 200;
}
void Multipart(const Request &req, Response &rsp)
{
    auto ret = req.has_file("file");
    if(ret == false)
    {
        std::cout << "not file upload\n";
        rsp.status = 400;
        return;
    }
    const auto& file = req.get_file_value("file");
    rsp.body.clear();
    rsp.body = file.filename; // 文件名称
    rsp.body += "\n";
    rsp.body += file.content; // 文件内容
    rsp.set_header("Content-Type", "text/plain");
    rsp.status = 200;
    return;
}
int main()
{
    httplib::Server sever; // 实例化Sever对象用于搭建服务器
    sever.Get("/hi", Hello); // 注册一个针对/hi的Get请求的处理函数映射关系
    sever.Get(R"(/numbers/(\d+))", Numbers);
    sever.Post("/multipart", Multipart);
    sever.listen("0.0.0.0", 9090);
    return 0;
}
$ g++ -o server httpserver.cpp -std=c++14 -lpthread
$ ./server

运行结果

在这里插入图片描述

注意:测试时一定要关闭防火墙,设置安全组开放端口

10. httplib库搭建简单客户端案例

#include "httplib.h"
#define SERVER_IP "你的服务器IP地址"
#define SERVER_PORT 9090

int main()
{
    httplib::Client client(SERVER_IP, SERVER_PORT); // 实例化client对象,用于搭建客户端
    // 以下仅为上传文件的测试,其他两个测试在浏览器上进行
    httplib::MultipartFormData item;
    item.name = "file"; // 该"file"匹配的就是服务器程序代码中的"file"
    item.filename = "hello.txt"; // 文件名
    item.content = "Hello World!"; // 文件内容
    item.content_type = "text/plain";
    
    httplib::MultipartFormDataItems items;
    items.push_back(item);

    auto res = client.Post("/multipart", items);
    std::cout << res->status << std::endl;
    std::cout << res->body << std::endl;
    return 0;
}

$ g++ -o client httpclient.cpp -std=c++14 -lpthread
$ ./client

运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1124678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python实现excel的数据提取

一文带你实现excel表格的数据提取 今天记录一下如何使用python提取Excel中符合特定条件的数据 在数据处理和分析的过程中&#xff0c;我们经常需要从Excel表格中提取特定条件下的数据。Python的pandas库为我们提供了方便的方法来进行数据查询和过滤。 Pandas 是 Python 语言…

代码随想录 Day26 贪心 01 全集 LeetCode455 分发饼干 LeetCodeT346摆动序列 LeetCdoe T53 最大子数组和

前言:贪心无套路 本质: 局部最优去推导全局最优 两个极端 贪心算法的难度一般要么特别简单,要么特别困难,所以我们只能多见识多做题,记住无需数学证明,因为两道贪心基本上毫无关系,我们只需要去思考局部最优即可 贪心的小例子 比如有一堆钞票&#xff0c;你可以拿走十张&#x…

vue 生命周期钩子函数 mounted()实例

在挂载后操作dom获取焦点。 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"w…

Maven3.9.2 bug IDEA指定配置文件不生效

Maven3.9.2 bug IDEA指定配置文件不生效 描述 运行新项目需要配置指定的settings.xml文件&#xff0c;一直报错找不到依赖&#xff0c;查看maven日志是从maven中心仓库找的依赖&#xff0c;自然找不到。 解决过程 清理idea缓存&#xff0c;仍然报错 删除/${username}/.m2/…

三分钟实现MQTT协议网关网口连接西门子SMART200PLC上传阿里云服务器

MQTT协议网关网口连接西门子SMART200PLC操作说明v1.4 目录 一. 使用流程 二. 准备工作 2.1 需要准备如下物品 2.2 LF220网关准备工作 2.3 PLC准备工作 2.4 电脑的准备工作 2.5 MQTT服务器准备工作 三. 阿里云IoT平台配置步骤 3.1 创建产品 3.2 添加设备 …

取证之查看本机保存的WiFi密码

一、电脑保存有WiFi密码&#xff0c;且正常连接该WiFi 1、打开网络适配器高级选项 2、双击无线网卡&#xff0c;选择无线属性 3、点击安全&#xff0c;显示字符&#xff0c;即可看到WiFi密码。 二、电脑保存有密码&#xff0c;但是没有链接WiFi。 1、查看wlan接口上的配置文件…

蓝桥杯每日一题0223.10.23

第几天 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 简单枚举&#xff08;用k来记录经过的天数&#xff09; #include<bits/stdc.h> using namespace std; bool is_ren(int n) {if(n % 400 0 || (n % 4 0 && n % 100 ! 0))return true;return false; } int …

推荐微软的开源课程《AI-For-Beginners》

今天给大家推荐一个对新手非常友好的AI入门课程《AI-For-Beginners》。 该课程由微软推出&#xff0c;为期12周&#xff0c;共24课时&#xff0c;对比Google的AI入门课更通俗易懂一些&#xff0c;强烈推荐刚入门的AI小白们学习&#xff01;而且是免费&#xff01;课程资源看文…

Matlab论文插图绘制模板第122期—函数折线图(fplot)

本期分享的是函数折线图的绘制模板。​ 所谓函数折线图&#xff0c;就是将自定义线函数进行可视化表达​。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有需要的朋友可以关注同名公号【阿昆的…

基于springboot基于会员制医疗预约服务管理系统项目【项目源码+论文说明】

基于springboot实现会员制医疗预约服务信息系统演示 摘要 会员制医疗预约服务管理信息系统是针对会员制医疗预约服务管理方面必不可少的一个部分。在会员制医疗预约服务管理的整个过程中&#xff0c;会员制医疗预约服务管理系统担负着最重要的角色。为满足如今日益复杂的管理需…

Java Spring 通过 AOP 实现方法参数的重新赋值、修改方法参数的取值

AOP 依赖 我创建的项目项目为 SpringBoot 项目 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.3</version></parent><dependency><groupId…

Linux:【Kafka-Java一】Spring实现kafka消息的简单发送

目录 一、创建maven项目 二、引入依赖 三、创建生产者 一、创建maven项目 1.1、创建maven项目不再多说 二、引入依赖 1.1、maven项目创建完成后&#xff0c;需要引入以下依赖 // kafka 依赖<dependency><groupId>org.apache.kafka</groupId><artifact…

GRE MGRE原理与配置

IPSec VPN用于在两个端点之间提供安全的IP通信&#xff0c;但只能加密并传播单播数据无法加密和传输语音、视频、动态路由协议信息等组播数据流量。通用路由封装协议GRE( Generic Routing Encapsulation )提供了将一种协议的报文封装在另一种协议报文中的机制&#xff0c;是一种…

华为云全新上线Serverless应用中心,支持一键构建文生图应用

近日&#xff0c;华为云全新上线Serverless应用中心&#xff0c;提供了大量应用模板&#xff0c;让用户能够一键部署函数和周边依赖资源&#xff0c;节省部署时间&#xff0c;快速上手将应用部署到华为云函数计算FunctionGraph&#xff0c;并一键开通周边依赖资源。 本次Serve…

微信小程序ios页面没有滚动下拉也会出现黑色背景

问题截图&#xff1a; 查了一下资料说有用一下方法解决的&#xff1a; 整体overflow: hidden&#xff0c;页面的内容将无法滚动&#xff08;试了一下没用&#xff09;&#xff1b;设置 -webkit-overflow-scrolling 和 touch-action 样式属性来禁用页面的拖动和拉拽操作&…

底层驱动day4作业

分布注册设备&#xff0c;实现文件和设备的绑定 代码&#xff1a; //head.h #ifndef __HEAD_H__ #define __HEAD_H__ #define PHY_RCC 0x50000A28 #define PHY_GPIOE_MODER 0x50006000 #define PHY_GPIOF_MODER 0x50007000 #define PHY_GPIOE_ODR 0x50006014 #define PHY_GPI…

VR虚拟现实技术在法院技能培训中的应用

开展法治宣传教育&#xff0c;是全面贯彻落实科学发展观的重要决策&#xff0c;也是保障和促进经济设备会发展和实施“十一五”规划的内在要求。为了让全民法治文化宣传深入人们群众中&#xff0c;突破性地采用VR虚拟现实、web3d开发和三维仿真技术&#xff0c;开发线上法治文化…

Git的标签管理

Git标签管理 创建标签操作标签小结 创建标签 在Git中打标签非常简单&#xff0c;首先&#xff0c;切换到需要打标签的分支上&#xff1a; $ git branch $ git checkout master 然后&#xff0c;敲命令git tag 就可以打一个新标签&#xff1a; $ git tag v1.0 可以用命令git …

大一新生必备电脑软件插件有哪些?

毕业老学姐倾情分享珍藏必备软件和浏览器插件&#xff01;拥有后生活明朗&#xff0c;学习效率UPUP&#xff01; 纯干货分享建议【点赞收藏】后观看 速览 Office全家桶-Word、Excel、Powerpoint大学生必备 火绒安全-计算机防病毒软件 AI助手-AI对话写作阅读助手&#xff0c;…

HCIP-MGRE实验

实验拓扑图 需求 1 R5为ISP &#xff0c;只能进行IP地址配置;其所有地址均配为公有IP地址 2 R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方; R2于R5之间使用ppp的chap认证&#xff0c;R5为主认证方; R3于R5之间使用HDLC封装。 3 R1/R2/R3构建一个MGRE环境&#xff0c;R1为…