目录
一,Jsoncpp库序列化和反序列化
二,bundle文件压缩库
2.1 文件压缩
2.2 文件解压
一,Jsoncpp库序列化和反序列化
首先我们需要先了解一下json是什么,json是一种数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。
char name = "小明";
int age = 18;
float score[3] = {88.5, 99, 58};
则json这种数据交换格式是将这多种数据对象组织成为一个字符串:
[
{
"姓名" : "小明",
"年龄" : 18,
"成绩" : [88.5, 99, 58]
},
{
"姓名" : "小黑",
"年龄" : 18,
"成绩" : [88.5, 99, 58]
}
]
json
数据类型:对象,数组,字符串,数字对象:使用花括号
{}
括起来的表示一个对象。数组:使用中括号
[]
括起来的表示一个数组。字符串:使用常规双引号
""
括起来的表示一个字符串数字:包括整形和浮点型,直接使用。
而Jsoncpp库主要用于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序列化类,低版本用这个更简单
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;
}
接下来我们来举例使用一下:
#include <iostream>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
{
// 序列化
const char *name1 = "张三";
int age1 = 18;
float grade1[3] = {77.1, 64.74, 56.11};
Json::Value val;
val["姓名"] = name1;
val["年龄"] = age1;
val["成绩"].append(grade1[0]);
val["成绩"].append(grade1[1]);
val["成绩"].append(grade1[2]);
Json::StreamWriterBuilder swb;
std::shared_ptr<Json::StreamWriter> writer_ptr(swb.newStreamWriter());
std::ostringstream sst;
writer_ptr->write(val, &sst);
std::cout << sst.str() << std::endl;
std::cout << "----------------------------------------------------" << std::endl;
// 反序列化
std::string str = R"({"姓名":"李四","年龄":24,"成绩":[71.1,60,50]})";
Json::Value root;
std::string err;
Json::CharReaderBuilder crb;
std::shared_ptr<Json::CharReader> read_ptr(crb.newCharReader());
read_ptr->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
const char *name2 = root["姓名"].asCString();
int age2 = root["年龄"].asInt();
float grade2[3] = {0};
grade2[0] = root["成绩"][0].asFloat();
grade2[1] = root["成绩"][1].asFloat();
grade2[2] = root["成绩"][2].asFloat();
std::cout << "姓名:" << name2 << std::endl;
std::cout << "年龄:" << age2 << std::endl;
for (auto f : grade2)
{
std::cout << f << " ";
}
std::cout << std::endl;
return 0;
}
二,bundle文件压缩库
BundleBundle
是一个嵌入式压缩库,支持23种压缩算法和2种存档格式。使用的时候只需要加入两个文件bundle.h
和bundl
e.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 );
}
2.1 文件压缩
#include <iostream>
#include <string>
#include <fstream>
#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;
}
2.2 文件解压
#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);
ifs.read(&body[0], fsize);
ifs.close();
std::string unpacked = bundle::unpack(body);//对压缩包数据解压缩
std::ofstream ofs;
ofs.open(ofilename, std::ios::binary);
ofs.write(&unpacked[0], unpacked.size());
ofs.close();
return 0;
}