云备份day02

📟作者主页:慢热的陕西人

🌴专栏链接:C++云备份项目

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

主要内容介绍了第三方库jsoncpp和bundle库的使用

在这里插入图片描述

文章目录

  • 云备份day02
    • 1.Json库的使用
      • 1.1JSON与JSONCPP简介
      • 1.2安装JSONCPP
      • 1.3JSONCPP的基本使用
        • 1.3.1读取JSON数据
        • 1.3.2写入JSON数据
      • 1.4json的数据对象类
        • 1.4.1 Json::Value
        • 1.4.2 Json::Reader
        • 1.4.3Json::Writer
      • 1.5json序列化和反序列化的例子
    • 2.bundle文件压缩库的使用
      • 2.1尝试使用bundle库来实现文件的压缩
      • 2.2使用bundle库来实现文件的解压缩

云备份day02

1.Json库的使用

在现代软件开发中,数据的交换与处理是不可或缺的一环,尤其是在多平台、多语言的环境下。这里,我们要探讨的是JSONCPP —— 一个处理JSON数据的C++库,它提供了一套丰富的API来解析、构造、操作和序列化JSON数据。让我们从头开始,逐步深入了解JSONCPP的使用。

1.1JSON与JSONCPP简介

**JSON(JavaScript Object Notation)**是一种轻量级的数据交换格式。它基于文本,易于人类阅读和编写,同时也易于机器解析和生成。JSON主要用于存储和交换文本信息,格式简洁明了,具有良好的自描述性,因此被广泛应用于Web API、配置文件和数据库之间的数据交换。

JSONCPP是一个在C++中处理JSON数据的库,它提供了强大的功能,包括读取JSON数据、写入JSON数据、数据操作和查询等。通过JSONCPP,开发者可以在C++项目中轻松地实现复杂的JSON数据处理任务。

1.2安装JSONCPP

在开始使用JSONCPP之前,首先需要将其集成到你的C++项目中。JSONCPP可以通过多种方式安装,包括源码编译、包管理器(如vcpkg、apt-get)或直接在某些IDE中添加依赖。

# 例如,使用apt-get在Ubuntu中安装JSONCPP
sudo apt-get install libjsoncpp-dev

1.3JSONCPP的基本使用

在JSONCPP中,Json::Value是最核心的类,它代表了JSON数据中的任意元素,无论是一个对象、数组还是基本数据类型。接下来,我们将通过一些基本示例来了解如何使用JSONCPP进行JSON数据的读取和写入。

1.3.1读取JSON数据

假设我们有一个JSON字符串,我们想要解析它并访问其中的数据。

#include <json/json.h>
#include <iostream>

int main() {
    std::string strJson = R"({
        "name": "John Doe",
        "age": 30,
        "is_student": false,
        "skills": ["C++", "Python", "JavaScript"]
    })";

    Json::Value root;   
    Json::Reader reader;
    bool parsingSuccessful = reader.parse(strJson, root);
    if (!parsingSuccessful) {
        std::cout << "Failed to parse JSON" << std::endl;
        return 1;
    }

    std::string name = root["name"].asString();
    int age = root["age"].asInt();
    bool isStudent = root["is_student"].asBool();
    std::cout << "Name: " << name << ", Age: " << age << ", Is Student: " << isStudent << std::endl;

    const Json::Value skills = root["skills"];
    for (int index = 0; index < skills.size(); ++index) {
        std::cout << "Skill " << index + 1 << ": " << skills[index].asString() << std::endl;
    }

    return 0;
}
1.3.2写入JSON数据

创建和修改JSON数据同样简单。我们可以通过操作Json::Value对象来构建一个JSON结构。

#include <json/json.h>
#include <iostream>

int main() {
    Json::Value root;
    root["name"] = "Jane Doe";
    root["age"] = 25;
    root["is_student"] = true;
    root["skills"].append("C++");
    root["skills"].append("Python");
    root["skills"].append("JavaScript");

    Json::StreamWriterBuilder builder;
    const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
    writer->write(root, &std::cout);
    std::cout << std::endl;

    return 0;
}

接下来我们将详细介绍:

1.4json的数据对象类

//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序列化类,低版本用这个更简单
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反序列化类,低版本用起来更简单
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;
}
1.4.1 Json::Value

Json::Value 是JsonCpp库中的核心类,用于表示JSON数据的所有可能类型:null、布尔值、整数、实数(浮点数)、字符串、数组和对象。

#include <json/json.h>
#include <string>
#include <iostream>

int main() {
    // 创建一个Json::Value对象
    Json::Value data;

    // 通过不同方式设置值
    data["integer"] = 1;  // 整数
    data["float"] = 1.1;  // 浮点数
    data["string"] = "example";  // 字符串
    data["boolean"] = true;  // 布尔值
    data["array"] = Json::arrayValue;  // 数组
    data["array"].append(1);  // 向数组中添加元素
    data["array"].append("two");
    data["object"] = Json::objectValue;  // 对象
    data["object"]["key"] = "value";  // 向对象中添加键值对

    // 打印生成的JSON字符串
    std::cout << data.toStyledString() << std::endl;

    return 0;
}
1.4.2 Json::Reader

Json::Reader 类用于将JSON格式的字符串解析为 Json::Value 对象。这对于读取JSON数据非常有用。

#include <json/json.h>
#include <string>
#include <iostream>

int main() {
    std::string str = "{\"age\": 25, \"name\": \"John\"}";

    Json::Value root;
    Json::Reader reader;

    bool parsingSuccessful = reader.parse(str, root);
    if (parsingSuccessful) {
        std::cout << "Name: " << root["name"].asString() << std::endl;
        std::cout << "Age: " << root["age"].asInt() << std::endl;
    } else {
        std::cerr << "Failed to parse JSON" << std::endl;
    }

    return 0;
}
1.4.3Json::Writer

Json::Writer 是一个抽象基类,定义了将 Json::Value 对象转换成JSON格式字符串的接口。Json::FastWriterJson::StyledWriterJson::StyledStreamWriter 是继承自 Json::Writer 的具体实现类,用于生成不同风格的JSON字符串。

由于JsonCpp的较新版本推荐使用 Json::Value 自带的 toStyledString 方法直接生成字符串,Json::Writer 及其派生类的使用变得不那么常见。不过,如果需要更复杂的定制化输出,这些类仍然很有用。

#include <json/json.h>
#include <string>
#include <iostream>

int main() {
    Json::Value root;
    root["action"] = "run";
    root["data"]["value"] = 10;

    // 使用StyledWriter生成格式化的JSON字符串
    Json::StyledWriter writer;
    std::string output = writer.write(root);

    std::cout << output << std::endl;

    return 0;
}

以上代码提供了使用JsonCpp处理JSON数据的基本方法,包括创建和操作JSON对象、解析JSON字符串和生成JSON字符串。

1.5json序列化和反序列化的例子

#include<iostream> // 引入标准输入输出流库,用于控制台输入输出。
#include<sstream> // 引入字符串流库,用于在内存中读写字符串。
#include<memory> // 引入智能指针库,提供对智能指针如 unique_ptr 的支持。
#include<string> // 引入字符串库,支持string类型的操作。
#include<jsoncpp/json/json.h> // 引入JsonCpp库,用于处理JSON数据的序列化与反序列化。
#include<cstring> // 引入字符串处理库。

using namespace std; // 使用标准命名空间,避免每次调用标准库时都需要前缀 std::。

int main() // 主函数,程序的入口点。
{
    const char* name = "小明"; // 定义常量字符指针,指向姓名字符串。
    int age = 18; // 定义整数变量,表示年龄。
    int score[] = {79, 82, 93}; // 定义整型数组,存储三个成绩。

    Json::Value rootw; // 创建Json::Value对象,用作JSON的根节点。

    rootw["姓名"] = name; // 向JSON对象添加“姓名”字段。
    rootw["年龄"] = age; // 向JSON对象添加“年龄”字段。
    // 循环添加成绩到JSON的“成绩”数组中。
    rootw["成绩"].append(score[0]);
    rootw["成绩"].append(score[1]);
    rootw["成绩"].append(score[2]);

    // 序列化JSON对象。
    Json::StreamWriterBuilder swb; // 创建StreamWriterBuilder对象,用于构建StreamWriter。
    unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter()); // 使用StreamWriterBuilder创建StreamWriter的unique_ptr。
    stringstream ss; // 创建一个stringstream对象,用作序列化的输出缓冲区。
    sw->write(rootw, &ss); // 使用StreamWriter将JSON对象序列化到stringstream。

    cout << ss.str() << endl; // 将序列化的JSON字符串输出到控制台。

    // 定义一个JSON字符串。
    string str = R"({"姓名" : "小明","年龄" : 18,"成绩" : [79, 82, 93]})";

    Json::Value rootr; // 创建用于反序列化的Json::Value对象。
    Json::CharReaderBuilder crb; // 创建CharReaderBuilder对象。
    string err; // 定义字符串以存储可能的错误信息。
    unique_ptr<Json::CharReader> cr(crb.newCharReader()); // 使用CharReaderBuilder创建CharReader的unique_ptr。
    // 尝试解析JSON字符串。
    bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &rootr, &err);
    if(ret == false) // 检查解析是否成功,这里有个逻辑错误,应该使用==比较。
    {
        cout << err << endl; // 如果解析失败,输出错误信息。
        return -1; // 并结束程序。
    }

    // 如果解析成功,输出解析得到的数据。
    cout << "姓名:" << rootr["姓名"].asString() << endl;
    cout << "年龄:" << rootr["年龄"].asInt() << endl;

    int sz = rootr["成绩"].size(); // 获取成绩数组的大小。
    cout << "成绩:";
    for(int i = 0; i < sz; ++i) cout << rootr["成绩"][i] << " "; // 循环输出每一项成绩。

    puts(""); // 输出换行。
    return 0; // 程序正常结束。
}

在这里插入图片描述

2.bundle文件压缩库的使用

Bundle是一个嵌入式C++压缩库,支持多种压缩算法和档案格式。设计上追求高压缩比和快速解压速度,可配置,且兼容C++03及C++11的可选特性。该库支持多种流和档案格式,如.bun和.zip,包括DEFLATE、LZMA、ZPAQ、LZ4、ZSTD、BROTLI等23种压缩算法。项目采用Zlib许可证,是一种宽松的使用许可。更多详情可以参考其GitHub仓库。

2.1尝试使用bundle库来实现文件的压缩

注意我们先将bundle.cppbundle.h都移动到当前的目录下,然后在编译的时候要连接pthread库.

#include<iostream>
#include<string>
#include<fstream>

#include"bundle.h"

using namespace std;

void Usage(char* argv[])
{
    cout << "Usage:" << argv[0] << " origin_file " << "Zip_file" << endl;
}

int main(int argc, char* argv[])
{
    if(argc != 3) 
    {
        Usage(argv);
        return -1;
    }

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

    ifstream ifs;
    ifs.open(ifilename, ios::binary);
    ifs.seekg(0, ios::end); 
    size_t fsz = ifs.tellg();
    ifs.seekg(0, ios::beg);
    string body;
    body.resize(fsz);
    ifs.read(&body[0], fsz);

    string packed = bundle::pack(bundle::LZIP, body);

    ofstream ofs;
    ofs.open(ofilename, ios::binary);
    ofs.write(&packed[0], packed.size());

    ifs.close();
    ofs.close();
    return 0;
}

压缩后的效果:其中b.cpp被压缩为b.cpp.lz

[mi@lavm-5wklnbmaja Pre_study]$ ls -lh
total 15M
-rw-rw-r-- 1 mi mi 5.4M Apr  2 19:54 b.cpp
-rw-rw-r-- 1 mi mi 668K Apr  2 19:55 b.cpp.lz
-rw-rw-r-- 1 mi mi 5.4M Apr  2 19:51 bundle.cpp
-rw-rw-r-- 1 mi mi  29K Apr  2 19:32 bundle.h
-rwxrwxr-x 1 mi mi 3.2M Apr  2 19:53 compress
-rw-rw-r-- 1 mi mi  790 Apr  2 19:56 compress.cpp
-rw-rw-r-- 1 mi mi 3.0K Apr  2 19:06 JsonTest.cpp

2.2使用bundle库来实现文件的解压缩

#include<iostream>   // 包含输入输出库
#include<string>     // 包含字符串库
#include<fstream>    // 包含文件操作库
#include"bundle.h"  // 包含定义的bundle库
using namespace std;
// 用于在参数数量不正确时显示正确的使用方式
void Usage(char* argv[])
{
    // 输出正确的使用方式
    cout << \"Usage:\" << argv[0] << \" Zip_file \" << \"UnZip_file\" << endl;
}
int main(int argc, char* argv[])
{
    // 如果参数数量不正确,显示使用方法并返回错误码
    if(argc != 3) 
    {
        Usage(argv);
        return -1;
    }
    // 获取压缩和解压文件的名字
    string ifilename = argv[1];
    string ofilename = argv[2];
    ifstream ifs;  // 创建一个ifstream 对象
    ifs.open(ifilename, ios::binary); // 以二进制方式打开压缩文件
    ifs.seekg(0, ios::end);  // 获取压缩文件的大小
    size_t fsize = ifs.tellg();
    ifs.seekg(0, ios::beg);  // 回到文件开头
    string body;
    body.resize(fsize);    // 将压缩文件的内容读入内存
    ifs.read(&body[0], fsize); // 读取文件内容
    ifs.close(); // 关闭压缩文件
    // 使用bundle库的unpack函数解压文件内容
    string unpacked = bundle::unpack(body);
    ofstream ofs;     // 创建一个ofstream 对象
    ofs.open(ofilename, ios::binary); //以二进制方式打开解压文件
    ofs.write(&unpacked[0], unpacked.size()); // 将解压后的内容写入解压文件
    // 关闭解压文件
    ofs.close();
    //主函数返回值
    return 0;
}

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第三十一天| 理论基础、LeetCode 455.分发饼干、376. 摆动序列、53. 最大子序和

一、理论基础 文章讲解&#xff1a;https://programmercarl.com/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 1.贪心的定义 贪心的本质是选择每一阶段的局部最优解&#xff0c;从而达到全局最优解。例如&#xff0c;有一堆钞票&#xff0c…

MySQL常见锁探究

MySQL常见锁探究 1. 各种锁类型1.1 全局锁1.2 表级锁1.2.1 表锁1.2.2 元数据锁&#xff08;MDL&#xff09;1.2.3 意向锁1.2.4 AUTO-INC 锁 1.3 行级锁1.3.1 Record Lock1.3.2 Gap Lock1.3.3 Next-Key Lock 2. MySQL是如何加锁的&#xff1f;2.1 什么 SQL 语句会加行级锁&#…

WPS 不登录无法使用基本功能的解决办法

使用wps时&#xff0c;常常有个比较让人烦恼的事&#xff0c;在不登录的情况下&#xff0c;新建或者打开文档时&#xff0c;wps不让你使用其基本的功能&#xff0c;如设置字体等&#xff0c;相关界面变成灰色&#xff0c;这时Wps提示用户登录注册或登录&#xff0c;但我又不想登…

喜讯 ChatGPT 3.5 免登录|免注册就可以使用了

https://chat.openai.com/ 直接访问openai 官网直接使用&#xff0c;当然还是要魔法的&#xff0c;不用再去用别人二次开发的&#xff0c;还有次数限制&#xff0c;还有开会员&#x1f605;才能用的。&#x1f600;试用啦一下&#xff0c;基本秒回答&#xff0c;能力也是在线的…

深入浅出 -- 系统架构之微服务架构常见的六种设计模式

面向服务的架构&#xff08;SOA&#xff09; 面向服务的架构&#xff08;SOA&#xff09;是一种设计方法&#xff0c;也是一个组件模型&#xff0c;它将应用程序的不同功能单元&#xff08;称为服务&#xff09;通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的…

软件工程导论

软件工程选择题复习笔记 一、软件工程学概述 用户使用不当、硬件可靠性差、对软件的错误认识属于软件危机的表现&#xff0c;不是原因软件危机&#xff0c;1960年以来&#xff0c;软件工程1968提出软件工程着重于建造一个软件系统 八个阶段可以归纳为计划(定义)阶段&#xf…

一次java.lang.NullPointerException的排查之旅

一次java.lang.NullPointerException的排查之旅 问题由来问题分析问题处理 问题由来 最近在项目中遇到了一个比较奇怪的java.lang.NullPointerException&#xff0c;就是说在自己的本地环境中&#xff0c;功能正常&#xff0c;运行无异常。但是测试环境点击同样的功能时却总是…

每日一练 寻找两个正序数组的中间数

题目参上&#xff0c;以下是解题思路&#xff1a; 首先&#xff0c;我们应该想到的一种方法是把两数组合并为一个整体的数组&#xff0c;然后返回其中位数即可。那么我们如何合并两数组呢&#xff1f;我们可以用归并排序&#xff0c;设置上下两指针&#xff0c;不断遍历返回较…

字节新作:图像生成质量超越DiT

&#x1f31f;每日更新最新高质量论文&#xff0c;关注我&#xff0c;时刻关注最新大模型进展。&#x1f31f; &#x1f4cc; 元数据概览&#xff1a; 标题&#xff1a;Visual Autoregressive Modeling: Scalable Image Generation via Next-Scale Prediction作者&#xff1a…

2012年认证杯SPSSPRO杯数学建模C题(第二阶段)碎片化趋势下的奥运会商业模式全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 C题 碎片化趋势下的奥运会商业模式 原题再现&#xff1a; 从 1984 年的美国洛杉矶奥运会开始&#xff0c;奥运会就不在成为一个“非卖品”&#xff0c;它在向观众诠释更高更快更强的体育精神的同时&#xff0c;也在攫取着巨大的商业价值&#…

LeetCode-热题100:21. 合并两个有序链表

题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a; l1 [1,2,4], l2 [1,3,4] 输出&#xff1a; [1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a; l1 [], l2 [] 输出…

什么是ICMP协议,如何防护ICMP攻击

一.什么是ICMP ICMP&#xff08;Internet Control Message Protocol&#xff09;是互联网控制报文协议&#xff0c;是TCP/IP协议族的一个子协议。它主要用于在IP网络中传递控制信息和错误消息&#xff0c;是IP协议的补充。ICMP协议是一种无连接协议&#xff0c;它不需要建立…

如何锁定鼠标光标在水平、垂直或45度对角线模式下移动 - 鼠标水平垂直移动锁定器简易教程

在我们进行精细工作例如如创建图标和图形设计时&#xff0c;通常需要我们对鼠标移动进行精确控制。一旦向左或向右轻微移动&#xff0c;都可能导致设计出错。若出现不必要的错误&#xff0c;我们极有可能不得不重新开始&#xff0c;这会令人感到非常沮丧。这种情况下&#xff0…

NIO基础知识

在学习Netty之前先要学习一下NIO相关的知识&#xff0c;因为Netty是基于NIO搭建的一套网络编程框架。 一. NIO 基础 non-blocking io 非阻塞 IO 1. 三大组件 1.1 Channel & Buffer channel 有一点类似于 stream&#xff0c;它就是读写数据的双向通道&#xff0c;可以从…

SSM实战项目——哈哈音乐(三)文件服务器模块开发

1、创建模块 创建一个子模块&#xff08;hami-fie&#xff09;&#xff0c;里面不写任何代码&#xff0c;专门用于文件上传的服务器 在hami-file的webapp下创建上传文件资源的文件夹&#xff0c;并引入资源&#xff08;图片、音频&#xff09; 2、pom.xml主配置文件中引入文件…

提升提测质量之研测共建

提升提测质量之研测共建 简介 你是否也有同样的困惑&#xff1f;跟进的需求&#xff0c;就在提测前一秒&#xff0c;被告知不能如期提测了&#xff0c;研测计划被打乱&#xff1b;提测的功能&#xff0c;犹如遇到不好的购物体验&#xff0c;缺斤短两&#xff0c;与prd预期不符…

Elasticsearch:我们如何演化处理二进制文档格式

作者&#xff1a;来自 Elastic Sean Story 从二进制文件中提取内容是一个常见的用例。一些 PDF 文件可能非常庞大 — 考虑到几 GB 甚至更多。Elastic 在处理此类文档方面已经取得了长足的进步&#xff0c;今天&#xff0c;我们很高兴地介绍我们的新工具 —— 数据提取服务&…

AopContext.currentProxy() 的代理对象错误(未被更新)问题

背景&#xff1a; 原来在springAOP的用法中&#xff0c;只有代理的类才会被切入&#xff0c;我们在controller层调用service的方法的时候&#xff0c;是可以被切入的&#xff0c;但是如果我们在service层 A方法中&#xff0c;调用B方法&#xff0c;切点切的是B方法&#xff0c;…

猫头虎技术分享 || 断网了,还能ping127.0.0.1吗?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

开源大语言模型(LLM)汇总(持续更新中)

随着ChatGPT的火爆&#xff0c;越来越多人希望在本地运行一个大语言模型。为此我维护了这个开源大语言模型汇总&#xff0c;跟踪每天不发的大语言模型和精调语言模型。 我将根据个模型采用的基础大模型进行分类&#xff0c;每个大模型下列出各派生模型。 Alpaca (Stanford) 斯…