云备份服务端——实用类工具实现

一,文件实用类设计实现

不管是客户端还是服务端,文件的传输备份都涉及到文件的读写,包括数据管理信息的持久化也是如此,因此首先设计封装文件操作类,这个类封装完毕之后,则在任意模块中对文件进行操作时都将变的简单化。

我们对文件的操作主要有以下几种,也就是我们文件实用类需要实现的功能

  • 获取文件大小
  • 获取文件最后一次修改时间(客户端在判断文件是否需要上传时需要用到)
  • 获取文件最后一次访问时间(判断文件是否属于热点文件就是通过最后一次访问时间)
  • 获取文件路径中的文件名
  • 向文件写入数据、获取文件数据
  • 获取文件指定位置,指定长度的数据(断点重传功能的实现需要该接口)
  • 判断文件是否存在
  • 创建文件目录、浏览文件目录
  • 压缩文件、解压文件
  • 删除文件

设计接口如下

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.c
        std::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;
        }
    };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值