赞
踩
hello !大家好呀! 欢迎大家来到我的Linux项目实战系列之《【百度云盘项目实践】:探索JSON与Bundle库的结合应用》,在这篇文章中,你将会学习到json数据格式,bundle库内对文件进行压缩与解压缩的过程,以及手绘UML图来帮助大家来理解,希望能让大家更能了解网络编程技术!!!
希望这篇文章能对你有所帮助,大家要是觉得我写的不错的话,那就点点免费的小爱心吧!(注:这章对于高性能服务器的实现非常重要哟!!!)
目录
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于JavaScript编程语言的一个子集,但因其文本格式清晰、易于解析和生成,被广泛用于数据交换和存储。JSON格式支持的数据结构包括对象(Object)和数组(Array)。
JSON对象是一个无序的键:值对集合。每个键值对中的键是一个字符串,后跟一个冒号,然后是值。值可以是字符串、数值、布尔值、数组、对象或null。例如:
- {
- "name": "张三",
- "age": 30,
- "isStudent": false,
- "courses": ["数学", "物理", "化学"],
- "address": {
- "city": "北京",
- "street": "长安街"
- }
- }
在这个例子中,name
、age
、isStudent
、courses
和address
是键,它们对应的值分别是字符串、数值、布尔值、数组和另一个对象。
JSON数组是一个有序的值列表,可以通过索引访问。数组中的值可以是字符串、数值、布尔值、数组、对象或null。例如:
- [
- {
- "name": "张三",
- "age": 30
- },
- {
- "name": "李四",
- "age": 25
- }
- ]
这个例子中,数组包含两个对象,每个对象都有name
和age
属性。
在C++中,可以使用如nlohmann/json
等库来解析和生成JSON数据。例如,使用这个库解析上述JSON对象:
- #include <nlohmann/json.hpp>
- #include <iostream>
-
- using json = nlohmann::json;
-
- int main() {
- std::string jsonString = "{\"name\": \"张三\", \"age\": 30}";
- json j = json::parse(jsonString);
-
- std::cout << "姓名: " << j["name"].get<std::string>() << std::endl;
- std::cout << "年龄: " << j["age"].get<int>() << std::endl;
-
- return 0;
- }
这段代码解析了一个包含姓名和年龄的JSON对象,并打印出这些信息。
JSON因其简洁和易用性,在Web应用、移动应用和许多其他场景中被广泛使用,特别是在数据交换和配置文件中。
在JSONCpp库中,
Json::Value
实例是表示JSON数据结构的基本对象。它可以表示JSON中的各种数据类型,如对象(Object)、数组(Array)、字符串(String)、数值(Number)、布尔值(Boolean)和null。Json::Value
实例是JSONCpp库的核心,用于创建、修改和访问JSON数据。
Json::Value
实例可以表示不同的数据类型。Json::Value
实例所表示的数据类型。- Json::Value value;
- value["key"] = "value"; // 创建一个键值对
- value["array"].append(1); // 向数组中添加元素
- std::string str = value["key"].asString();
- int num = value["array"][0].asInt();
- if (value.isObject()) {
- // 处理对象
- }
- if (value.isArray()) {
- // 处理数组
- }
- // 遍历对象
- for (Json::Value::const_iterator it = value.begin(); it != value.end(); ++it) {
- std::string key = it.key().asString();
- Json::Value keyValue = *it;
- // 处理键值对
- }
-
- // 遍历数组
- for (unsigned int i = 0; i < value.size(); ++i) {
- Json::Value arrayElement = value[i];
- // 处理数组元素
- }
使用场景
- 序列化:将C++数据结构转换为JSON字符串。
- 反序列化:将JSON字符串解析回C++数据结构。
- 数据交换:在不同系统或服务间交换数据。
- 配置文件:读取和写入配置数据。
Json::Value
实例是JSONCpp库的基础,通过它可以轻松地处理复杂的JSON数据结构。
在C++中,序列化是指将数据结构(如对象、数组等)转换为JSON字符串的过程,而反序列化则是将JSON字符串解析回相应的数据结构。使用如
nlohmann/json
库可以方便地进行这些操作。
在JSONCpp库中,newStreamWriter()
和newCharReader()
是用于JSON数据序列化和反序列化的重要函数。
newStreamWriter()
函数是Json::StreamWriterBuilder
类的一个方法,用于创建一个Json::StreamWriter
对象,该对象负责将Json::Value
对象转换为JSON格式的字符串。
作用
Json::Value
对象转换为JSON字符串。使用方法
StreamWriterBuilder
实例。newStreamWriter()
创建StreamWriter
对象。StreamWriter
的write()
方法将Json::Value
对象转换为字符串。示例
- Json::StreamWriterBuilder swb;
- std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
- stringstream ss;
- sw->write(root, &ss); // 将root序列化为JSON字符串,存储在ss中
newCharReader()
函数是Json::CharReaderBuilder
类的一个方法,用于创建一个Json::CharReader
对象,该对象负责将JSON字符串解析为Json::Value
对象。
作用
Json::Value
对象。使用方法
CharReaderBuilder
实例。newCharReader()
创建CharReader
对象。CharReader
的parse()
方法将JSON字符串解析为Json::Value
对象。示例
- Json::CharReaderBuilder cwb;
- unique_ptr<Json::CharReader> cw(cwb.newCharReader());
- string err;
- bool ret = cw->parse(json_str.c_str(), json_str.c_str() + json_str.size(), &root2, &err);
- // 解析json_str到root2,如果失败,错误信息存储在err中
总结
newStreamWriter()
和newCharReader()
是JSONCpp库中用于JSON数据序列化和反序列化的重要工具。newStreamWriter()
用于创建一个可以将Json::Value
对象转换为JSON字符串的StreamWriter
对象,而newCharReader()
用于创建一个可以将JSON字符串解析回Json::Value
对象的CharReader
对象。这些功能在处理JSON数据时非常关键,尤其是在需要与JSON格式数据进行交互的应用程序中。
这是一个典型的json数据序列号与反序列化的程序:
- #include<iostream>
- #include<sstream>
- #include<string>
- #include<memory>
- #include<jsoncpp/json/json.h>
- using namespace std;
-
- int main(){
- const char * name = "小明";
- int age = 18 ;
- float score[]= {77.5 , 88 ,93.6};
- //创建一个Value实例
- Json::Value root;
-
- //向Value实例中添加数据
- root["姓名"] = name;
- root["年龄"] = age;
- root["成绩"].append(score[0]);
- root["成绩"].append(score[1]);
- root["成绩"].append(score[2]);
-
- //创建一个StreamWriterBuilder实例
- Json::StreamWriterBuilder swb ;
-
- std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
-
- stringstream ss;
- //开始序列化,json序列化的字符串保存在ss中
- sw->write(root , &ss);
- cout<<ss.str()<<endl;
-
- //反序列化过程
- string json_str = ss.str();//获取json字符串
-
- Json::Value root2;
-
- Json::CharReaderBuilder cwb;
-
- unique_ptr<Json::CharReader> cw(cwb.newCharReader());
-
- string err;
- //反序列化过程
- bool ret = cw->parse(json_str.c_str() ,json_str.c_str() + json_str.size() , &root2 , &err);
- if(ret == false){
- cout<<"反序列化失败"<< err <<endl;
- }
-
- // 输出反序列化后的数据
- cout << "姓名: " << root2["姓名"].asCString() << endl;
- cout << "年龄: " << root2["年龄"].asInt() << endl;
- cout << "成绩: ";
- for (int i = 0; i < root2["成绩"].size(); ++i) {
- cout << root2["成绩"][i].asFloat() << " ";
- }
- cout << endl;
-
-
- return 0;
- }
bundle库中是有关于文件压缩与解压缩的23中方法的一个库,我们在云盘项目中,当用户进行文件的上传与下载时,我们需要对文件进行压缩与解压缩的过程,此时我们可以直接调用bundle库中的对应API来对我们文件进行处理,由于这个库内容比较简单,我就展示一个简单的示例使用程序:
这是压缩程序:当我们选择一个文件,可以按照我们指定的方式进行压缩为指定的文件。
- #include<iostream>
- #include<string>
- #include<fstream>
- #include"bundle.h"
- using namespace std;
- 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;
- }
这是我们压缩前httplib.h文件的大小,为321K。
我们进行压缩为.lz压缩包后: 明显我们的压缩包大小变成了49k,压缩比例还是很客观的。
这里给一个文件解压到另外一个文件的程序:
- #include<iostream>
- #include<string>
- #include<fstream>
- #include"bundle.h"
- using namespace std;
- int main(int argc , char *argv[]){
- if(argc <3){
- cout <<"argv[1]是压缩包名称"<<endl;
- cout<<"argv[2]是解压后的文件名称"<<endl;
- return -1;
- }
- string ifilename = argv[1] ;//获取压缩包名称
- string ofilename = argv[2];//获取解压后的文件名
-
- ifstream ifs;
- ifs.open(ifilename ,std::ios::binary);//打开压缩包
- ifs.seekg(0 , ios::end);//跳转到文件末尾
- size_t fsize = ifs.tellg();//获取文件大小
- ifs.seekg(0 ,ios::beg);//跳转到起始位置
-
- std::string body;
- body.resize(fsize);
- ifs.read(&body[0],fsize);//将压缩包数据传入body
- ifs.close();
-
- string unpacked = bundle::unpack(body);//进行解压缩,数据存入unpacked
-
- ofstream ofs ;
- ofs.open(ofilename, std::ios::binary);
- ofs.write(&unpacked[0] , unpacked.size());//数据写入解压文件
- ofs.close();
-
-
-
- return 0;
- }
这个程序的实机演示和上面差不多,大家可以自己试试,这里不过多演示了。
好啦!到这里这篇文章就结束啦,关于实例代码中我写了很多注释,如果大家还有不懂得,可以评论区或者私信我都可以哦!! 感谢大家的阅读,我还会持续创造网络编程相
关内容的,记得点点小爱心和关注哟!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。