云备份客户端——客户端整体设计框架以及实用类工具实现

一,客户端整体框架

客户端要实现的功能和服务端相比相对简单,客户端要实现的功能是自动对指定文件中的文件进行备份,也就是定时对指定文件进行扫描,根据文件信息判断文件,符合要求(新文件或者被修改过的文件)进行上传

因此我们客户端大概需要实现下面三个模块

  • 数据管理模块:管理备份文件的文件信息,后续需要通过该信息判断文件是否上传
  • 目录遍历模块:定时遍历指定文件下的所有文件
  • 文件备份模块:遍历文件时,根据文件信息判断是否上传

开发环境

由于我们客户端大多是给windows用户使用的,因此客户端在Windows上用vs2019进行开发

二,实用工具类实现

客户端的实用工具类的实现和服务端是一样的,但是功能少了些,例如压缩解压缩,同时因为vs2019上按照Json库不太方便,因此Json序列化和Json反序列化也不在使用,而在数据管理模块中数据存储时用到的序列化和反序列化,由我们自己完成。

cpp 复制代码
#ifndef _MY_UTIL_
#define _MY_UTIL_
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 1
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>
#include <sstream>
#include <experimental/filesystem>
#include <sys/stat.h>

namespace mjw_cloud
{
    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()
        {
            //这里由于时Windows下,因此目录符号需要改变
            /*int pos = _filename.find_last_of("/");*/
            int pos = _filename.find_last_of("\\");
            if (pos < 0)
            {
                if(!_filename.empty()) return _filename;
                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)
        {
            CreateDirectory();
            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 Remove()
        {
            if (Exists() == false)
            {
                std::cout << "object file unexist" << std::endl;
                return false;
            }
            remove(_filename.c_str());
            return true;
        }



    private:
        std::string _filename;
    };

}

#endif
相关推荐
小赵还有头发19 小时前
安装Ceres与glog
linux·学习·无人机·ceres·glog
xiaoye-duck20 小时前
C++ string 类使用超全攻略(上):创建、遍历及容量操作深度解析
c++·stl
负二代0.020 小时前
Linux下的网络管理
linux·网络
csdn_aspnet20 小时前
C++跨平台开发,分享一些用C++实现多平台兼容的工程难题与解决方案
c++
s_daqing20 小时前
ubuntu(arm)安装redis
linux·redis·ubuntu
林鸿群20 小时前
ubuntu 26.04 安装mysql-server
linux·mysql·ubuntu
betazhou20 小时前
rsync使用案例分析
linux·运维·服务器·rsync·同步数据
linweidong20 小时前
C++大型系统中如何组织头文件和依赖树?
java·c++·架构
橘子师兄21 小时前
C++AI大模型接入SDK—环境搭建
开发语言·c++·人工智能
偷星星的贼1121 小时前
C++中的状态机实现
开发语言·c++·算法