一,文件实用类设计实现
不管是客户端还是服务端,文件的传输备份都涉及到文件的读写,包括数据管理信息的持久化也是如此,因此首先设计封装文件操作类,这个类封装完毕之后,则在任意模块中对文件进行操作时都将变的简单化。
我们对文件的操作主要有以下几种,也就是我们文件实用类需要实现的功能
- 获取文件大小
- 获取文件最后一次修改时间(客户端在判断文件是否需要上传时需要用到)
- 获取文件最后一次访问时间(判断文件是否属于热点文件就是通过最后一次访问时间)
- 获取文件路径中的文件名
- 向文件写入数据、获取文件数据
- 获取文件指定位置,指定长度的数据(断点重传功能的实现需要该接口)
- 判断文件是否存在
- 创建文件目录、浏览文件目录
- 压缩文件、解压文件
- 删除文件
设计接口如下
class FileUtil{public://获取文件大小size_t size();//获取文件最后一次修改时间&最后一次访问时间time_t LastMTime();time_t LastATime();//获取文件路径名中的文件名std::string FileName();//向文件写入数据&向文件读取数据bool SetContent(const std::string& body);bool GetContent(std::string* body);//获取文件指定位置指定长度字符串bool GetPosLen(std::string* body,size_t pos,size_t len);//判断文件是否存在bool Exists();//创建文件目录&获取文件目录bool CreateDirectory();bool ScanDirectory();//压缩文件&解压文件bool Compress(const std::string& packname);bool UnCompress(const std::string& filename);bool Remove();private:std::string _filename;};
代码实现如下
注意创建目录和浏览目录文件用到了filesystem库,该库使用手册如下所示
Filesystem library - cppreference.com
namespace fs=std::experimental::filesystem;class FileUtil{public:FileUtil(const std::string &filename): _filename(filename){}// 获取文件大小size_t FileSize(){struct stat st;if (stat(_filename.c_str(), &st) < 0){std::cout << "get file attributes failed" << std::endl;return -1;}return st.st_size;}// 获取文件最后一次修改时间&最后一次访问时间time_t LastMTime(){struct stat st;if (stat(_filename.c_str(), &st) < 0){std::cout << "get file attributes failed" << std::endl;return -1;}return st.st_mtime;}time_t LastATime(){struct stat st;if (stat(_filename.c_str(), &st) < 0){std::cout << "get file attributes failed" << std::endl;return -1;}return st.st_atime;}// 获取文件路径名中的文件名//./abc/test.c ->test.cstd::string FileName(){int pos = _filename.find_last_of("/");if (pos < 0){std::cout << "filename error" << std::endl;return nullptr;}return _filename.substr(pos + 1);}// 获取文件指定位置指定长度字符串bool GetPosLen(std::string *body, size_t pos, size_t len){std::ifstream ifs(_filename, std::ios::binary);if (ifs.is_open() == false){std::cout << "open file failed" << std::endl;return false;}size_t size = this->FileSize();if (pos + len > size){std::cout << "Get filecontent is be illegal" << std::endl;return false;}ifs.seekg(pos, ifs.beg);body->resize(size);ifs.read(&(*body)[0], len);if (ifs.good() == false){std::cout << "read file failed" << std::endl;return false;}ifs.close();return true;}// 向文件写入数据&向文件读取数据bool SetContent(const std::string &body){std::ofstream ofs(_filename, std::ios::binary);if (ofs.is_open() == false){std::cout << "SetContent open file failed" << std::endl;return false;}ofs.write(&body[0], body.size());if (ofs.good() == false){std::cout << "write file failed" << std::endl;return false;}ofs.close();return true;}bool GetContent(std::string *body){size_t fsize = this->FileSize();return GetPosLen(body, 0, fsize);}// 判断文件是否存在bool Exists(){struct stat sm;return stat(_filename.c_str(), &sm) == 0;}// 创建文件目录&获取文件目录bool CreateDirectory(){if(Exists()) return true;return fs::create_directories(_filename);}bool ScanDirectory(std::vector<std::string> *arry){for (auto &i : fs::directory_iterator(_filename)){if(fs::is_directory(i)==true)//如果文件是路径名则跳过{continue;}arry->push_back(fs::path(i).relative_path().string());}return true;}// 压缩文件&解压文件bool Compress(const std::string &packname){// 1.读取文件内容std::string filebody;if (GetContent(&filebody) == false){std::cout << "get file body failed" << std::endl;return false;}// 2.压缩获取的内容std::string packbody;packbody = bundle::pack(bundle::LZIP, filebody);// 3.将压缩的数据放到压缩包文件中FileUtil fu(packname);if (fu.SetContent(packbody) == false){std::cout << "compress write failed" << std::endl;return false;}return true;}bool UnCompress(const std::string &filename){// 1.读取压缩文件内容std::string packbody;if (GetContent(&packbody) == false){std::cout << "get pack file body failed" << std::endl;return false;}// 2.解压读到的内容std::string filebody;filebody = bundle::unpack(packbody);// 3.将解压后的内容放入文件中FileUtil fu(filename);if (fu.SetContent(filebody) == false){std::cout << "file write failed" << std::endl;return false;}return true;}bool Remove(){if (Exists() == false){std::cout << "object file unexist" << std::endl;return false;}remove(_filename.c_str());return true;}private:// 用于类内使用bool exists(const std::string &filename){struct stat sm;return stat(filename.c_str(), &sm) == 0;}private:std::string _filename;};
测试代码
#include "util.hpp"void Utiltest()
{// 测试大小,最后修改时间,最后访问时间mjw_cloud::FileUtil fu("./test1.txt");std::cout << fu.FileSize() << std::endl;std::cout << fu.LastMTime() << std::endl;std::cout << fu.LastATime() << std::endl;std::cout << "--------------------------------------" << std::endl;// 测试获取文件名,文件写入,文件读取std::cout << fu.FileName() << std::endl;std::string write("hello,word\n");std::cout << write << ":";fu.SetContent(write);std::string read;fu.GetContent(&read);std::cout << read << std::endl;std::cout << "--------------------------------------" << std::endl;// 压缩文件,解压文件fu.Compress("./test1.lzip");std::cout << "压缩成功\n"<< std::endl;fu.UnCompress("./test1_lzip.txt");std::cout << "解压成功\n"<< std::endl;std::cout << "--------------------------------------" << std::endl;// 创建目录.获取文件目录mjw_cloud::FileUtil ex("./a/b/c");ex.CreateDirectory();std::vector<std::string> vs;ex.ScanDirectory(&vs);for(auto v:vs){std::cout<<v<<std::endl;}std::cout << "--------------------------------------" << std::endl;// 序列化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]);std::string str;mjw_cloud::JsonUtil::Serialize(val, &str);std::cout << str << std::endl;std::cout << "--------------------------------------" << std::endl;Json::Value root;mjw_cloud::JsonUtil::UnSerialize(str, &root);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;std::cout << "--------------------------------------" << std::endl;
}
结果如下
二,Json实用类实现
该类主要是对Json序列化反序列化的通用代码进行一个封装,减少重复代码的实用
/*util.hpp*/class JsonUtil{public:static bool Serialize(const Json::Value &root, std::string *str){Json::StreamWriterBuilder swb;std::shared_ptr<Json::StreamWriter> writer_ptr(swb.newStreamWriter());std::ostringstream sst;writer_ptr->write(root, &sst);*str = sst.str();return true;}static bool UnSerialize(const std::string &str, 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);return true;}};