【百度云盘项目实践(1)】:探索JSON与Bundle库的结合应用 ...

打印 上一主题 下一主题

主题 529|帖子 529|积分 1587

 

   hello !大家好呀! 欢迎大家来到我的Linux项目实战系列之《【百度云盘项目实践】:探索JSON与Bundle库的结合应用》,在这篇文章中,你将会学习到json数据格式,bundle库内对文件进行压缩与解压缩的过程,以及手绘UML图来帮助大家来明白,希望能让大家更能了解网络编程技能!!!
  希望这篇文章能对你有所帮助,大家要是觉得我写的不错的话,那就点点免费的小爱心吧!(注:这章对于高性能服务器的实现非常紧张哟!!!)
  
           
  目录
 一.Json
 1.1 json数据
JSON对象
JSON数组
JSON语法规则
JSON与C++的结合使用
1.2 Value实例
主要特性
常用操作
使用场景
1.3 json数据的序列化与反序列化
newStreamWriter()
newCharReader()
1.4 代码实例
二. bundle库 
文件压缩:
 文件解压:


 
 一.Json

 1.1 json数据

        
    JSON(JavaScript Object Notation)是一种轻量级的数据互换格式。它基于JavaScript编程语言的一个子集,但因其文本格式清楚、易于分析和生成,被广泛用于数据互换和存储。JSON格式支持的数据结构包括对象(Object)和数组(Array)。
JSON对象

JSON对象是一个无序的键:值对集合。每个键值对中的键是一个字符串,后跟一个冒号,然后是值。值可以是字符串、数值、布尔值、数组、对象或null。比方:
  1. {
  2.   "name": "张三",
  3.   "age": 30,
  4.   "isStudent": false,
  5.   "courses": ["数学", "物理", "化学"],
  6.   "address": {
  7.     "city": "北京",
  8.     "street": "长安街"
  9.   }
  10. }
复制代码
在这个例子中,name、age、isStudent、courses和address是键,它们对应的值分别是字符串、数值、布尔值、数组和另一个对象。
JSON数组

JSON数组是一个有序的值列表,可以通过索引访问。数组中的值可以是字符串、数值、布尔值、数组、对象或null。比方:
  1. [
  2.   {
  3.     "name": "张三",
  4.     "age": 30
  5.   },
  6.   {
  7.     "name": "李四",
  8.     "age": 25
  9.   }
  10. ]
复制代码
这个例子中,数组包含两个对象,每个对象都有name和age属性。
JSON语法规则



  • 数据在键值对中
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组
JSON与C++的结合使用

在C++中,可以使用如nlohmann/json等库来分析和生成JSON数据。比方,使用这个库分析上述JSON对象:
  1. #include <nlohmann/json.hpp>
  2. #include <iostream>
  3. using json = nlohmann::json;
  4. int main() {
  5.     std::string jsonString = "{"name": "张三", "age": 30}";
  6.     json j = json::parse(jsonString);
  7.     std::cout << "姓名: " << j["name"].get<std::string>() << std::endl;
  8.     std::cout << "年龄: " << j["age"].get<int>() << std::endl;
  9.     return 0;
  10. }
复制代码
这段代码分析了一个包含姓名和年事的JSON对象,并打印出这些信息。
JSON因其简便和易用性,在Web应用、移动应用和很多其他场景中被广泛使用,特别是在数据互换和设置文件中。

1.2 Value实例

   在JSONCpp库中,Json::Value实例是表示JSON数据结构的根本对象。它可以表示JSON中的各种数据范例,如对象(Object)、数组(Array)、字符串(String)、数值(Number)、布尔值(Boolean)和null。Json::Value实例是JSONCpp库的焦点,用于创建、修改和访问JSON数据。
  主要特性



  • 多态性:一个Json::Value实例可以表示不同的数据范例。
  • 动态性:可以在运行时改变Json::Value实例所表示的数据范例。
  • 易于使用:通过简单的API,可以方便地操作JSON数据。
常用操作



  • 创建和赋值
    1. Json::Value value;
    2. value["key"] = "value";  // 创建一个键值对
    3. value["array"].append(1);  // 向数组中添加元素
    复制代码
  • 访问数据
    1. std::string str = value["key"].asString();
    2. int num = value["array"][0].asInt();
    复制代码
  • 检查数据范例
    1. if (value.isObject()) {
    2.     // 处理对象
    3. }
    4. if (value.isArray()) {
    5.     // 处理数组
    6. }
    复制代码
  • 遍历对象和数组
    1. // 遍历对象
    2. for (Json::Value::const_iterator it = value.begin(); it != value.end(); ++it) {
    3.     std::string key = it.key().asString();
    4.     Json::Value keyValue = *it;
    5.     // 处理键值对
    6. }
    7. // 遍历数组
    8. for (unsigned int i = 0; i < value.size(); ++i) {
    9.     Json::Value arrayElement = value[i];
    10.     // 处理数组元素
    11. }
    复制代码
   使用场景

  

  • 序列化:将C++数据结构转换为JSON字符串。
  • 反序列化:将JSON字符串分析回C++数据结构。
  • 数据互换:在不同体系或服务间互换数据。
  • 设置文件:读取和写入设置数据。
  Json::Value实例是JSONCpp库的基础,通过它可以轻松地处置惩罚复杂的JSON数据结构。
   
1.3 json数据的序列化与反序列化

   在C++中,序列化是指将数据结构(如对象、数组等)转换为JSON字符串的过程,而反序列化则是将JSON字符串分析回相应的数据结构。使用如nlohmann/json库可以方便地进行这些操作。
   
  在JSONCpp库中,newStreamWriter()和newCharReader()是用于JSON数据序列化和反序列化的紧张函数。
newStreamWriter()

newStreamWriter()函数是Json::StreamWriterBuilder类的一个方法,用于创建一个Json::StreamWriter对象,该对象负责将Json::Value对象转换为JSON格式的字符串。
作用


  • 序列化:将C++中的Json::Value对象转换为JSON字符串。
  • 格式化:可以设置缩进、空格等格式化选项,使生成的JSON字符串更易于阅读。
使用方法

  • 创建StreamWriterBuilder实例。
  • 通过newStreamWriter()创建StreamWriter对象。
  • 使用StreamWriter的write()方法将Json::Value对象转换为字符串。
示例
  1. Json::StreamWriterBuilder swb;
  2. std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
  3. stringstream ss;
  4. sw->write(root, &ss);  // 将root序列化为JSON字符串,存储在ss中
复制代码
newCharReader()

newCharReader()函数是Json::CharReaderBuilder类的一个方法,用于创建一个Json::CharReader对象,该对象负责将JSON字符串分析为Json::Value对象。
作用


  • 反序列化:将JSON字符串分析回C++中的Json::Value对象。
  • 错误处置惩罚:在分析过程中,如果遇到错误,可以提供错误信息。
使用方法

  • 创建CharReaderBuilder实例。
  • 通过newCharReader()创建CharReader对象。
  • 使用CharReader的parse()方法将JSON字符串分析为Json::Value对象。
示例
  1. Json::CharReaderBuilder cwb;
  2. unique_ptr<Json::CharReader> cw(cwb.newCharReader());
  3. string err;
  4. bool ret = cw->parse(json_str.c_str(), json_str.c_str() + json_str.size(), &root2, &err);
  5. // 解析json_str到root2,如果失败,错误信息存储在err中
复制代码
  总结
  newStreamWriter()和newCharReader()是JSONCpp库中用于JSON数据序列化和反序列化的紧张工具。newStreamWriter()用于创建一个可以将Json::Value对象转换为JSON字符串的StreamWriter对象,而newCharReader()用于创建一个可以将JSON字符串分析回Json::Value对象的CharReader对象。这些功能在处置惩罚JSON数据时非常关键,尤其是在需要与JSON格式数据进行交互的应用步伐中。
  1.4 代码实例

        这是一个典型的json数据序列号与反序列化的步伐:
  1. #include<iostream>
  2. #include<sstream>
  3. #include<string>
  4. #include<memory>
  5. #include<jsoncpp/json/json.h>
  6. using namespace std;
  7. int main(){
  8.     const char * name = "小明";
  9.     int age = 18 ;
  10.     float score[]= {77.5 , 88 ,93.6};
  11.     //创建一个Value实例
  12.     Json::Value root;
  13.     //向Value实例中添加数据
  14.     root["姓名"] = name;
  15.     root["年龄"] = age;
  16.     root["成绩"].append(score[0]);
  17.     root["成绩"].append(score[1]);
  18.     root["成绩"].append(score[2]);
  19.     //创建一个StreamWriterBuilder实例
  20.     Json::StreamWriterBuilder swb ;
  21.     std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
  22.     stringstream ss;
  23.     //开始序列化,json序列化的字符串保存在ss中
  24.     sw->write(root , &ss);
  25.     cout<<ss.str()<<endl;
  26.     //反序列化过程
  27.     string json_str = ss.str();//获取json字符串
  28.     Json::Value root2;
  29.     Json::CharReaderBuilder cwb;
  30.     unique_ptr<Json::CharReader> cw(cwb.newCharReader());
  31.     string err;
  32.     //反序列化过程
  33.     bool ret = cw->parse(json_str.c_str() ,json_str.c_str() + json_str.size() , &root2 , &err);
  34.     if(ret == false){
  35.         cout<<"反序列化失败"<< err <<endl;
  36.     }
  37.     // 输出反序列化后的数据
  38.     cout << "姓名: " << root2["姓名"].asCString() << endl;
  39.     cout << "年龄: " << root2["年龄"].asInt() << endl;
  40.     cout << "成绩: ";
  41.     for (int i = 0; i < root2["成绩"].size(); ++i) {
  42.         cout << root2["成绩"][i].asFloat() << " ";
  43.     }
  44.     cout << endl;
  45.     return 0;
  46. }
复制代码
 
二. bundle库 

           bundle库中是有关于文件压缩与解压缩的23中方法的一个库,我们在云盘项目中,当用户进行文件的上传与下载时,我们需要对文件进行压缩与解压缩的过程,此时我们可以直接调用bundle库中的对应API来对我们文件进行处置惩罚,由于这个库内容比力简单,我就展示一个简单的示例使用步伐:
  文件压缩:

这是压缩步伐:当我们选择一个文件,可以按照我们指定的方式进行压缩为指定的文件。
  1. #include<iostream>
  2. #include<string>
  3. #include<fstream>
  4. #include"bundle.h"
  5. using namespace std;
  6. int main(int argc , char * argv[]){
  7.     std::cout<<"argv[1]是原始文件名字\n" ;
  8.     std ::cout<<"argv[2]是压缩包名字\n";
  9.     if(argc < 3) return -1;
  10.     std::string ifilename = argv[1];
  11.     std::string ofilename = argv[2];
  12.     std::ifstream ifs;//创建文件输入输出流
  13.     ifs.open(ifilename , std::ios::binary);//二进制打开文件
  14.     ifs.seekg(0,std::ios::end);//跳转到文件末尾
  15.     size_t fsize = ifs.tellg();//获取文件大小
  16.     ifs.seekg(0,std::ios::beg);//跳转到文件起始
  17.     std::string body;
  18.     body.resize(fsize);//调整body大小为文件大小
  19.     ifs.read(&body[0],fsize);//读取文件所有数据到body
  20.     std::string packed = bundle::pack(bundle::LZIP,body);//以Lzip格式压缩文件
  21.     std::ofstream ofs;
  22.     ofs.open(ofilename, std::ios::binary);//打开压缩包
  23.     ofs.write(&packed[0],packed.size());//将压缩后的文件写入压缩包文件
  24.     ifs.close();
  25.     ofs.close();
  26.    
  27.     return 0;
  28. }
复制代码
这是我们压缩前httplib.h文件的巨细,为321K。
 

我们进行压缩为.lz压缩包后: 显着我们的压缩包巨细变成了49k,压缩比例还是很客观的。
 

 
 文件解压:

这里给一个文件解压到另外一个文件的步伐:
  1. #include<iostream>
  2. #include<string>
  3. #include<fstream>
  4. #include"bundle.h"
  5. using namespace std;
  6. int main(int argc , char *argv[]){
  7.     if(argc <3){
  8.         cout <<"argv[1]是压缩包名称"<<endl;
  9.         cout<<"argv[2]是解压后的文件名称"<<endl;
  10.         return -1;
  11.     }
  12.     string ifilename = argv[1] ;//获取压缩包名称
  13.     string ofilename = argv[2];//获取解压后的文件名
  14.     ifstream ifs;
  15.     ifs.open(ifilename ,std::ios::binary);//打开压缩包
  16.     ifs.seekg(0 , ios::end);//跳转到文件末尾
  17.     size_t fsize = ifs.tellg();//获取文件大小
  18.     ifs.seekg(0 ,ios::beg);//跳转到起始位置
  19.     std::string body;
  20.     body.resize(fsize);
  21.     ifs.read(&body[0],fsize);//将压缩包数据传入body
  22.     ifs.close();
  23.     string unpacked = bundle::unpack(body);//进行解压缩,数据存入unpacked
  24.     ofstream ofs ;
  25.     ofs.open(ofilename, std::ios::binary);
  26.     ofs.write(&unpacked[0] , unpacked.size());//数据写入解压文件
  27.     ofs.close();
  28.     return 0;
  29. }
复制代码
这个步伐的实机演示和上面差不多,大家可以自己试试,这里不外多演示了。
          好啦!到这里这篇文章就结束啦,关于实例代码中我写了很多注释,如果大家还有不懂得,可以批评区或者私信我都可以哦
!! 感谢大家的阅读,我还会连续创造网络编程相
  关内容的,记得点点小爱心和关注哟!
  
   
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

耶耶耶耶耶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表