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

一,客户端整体框架

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

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

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

开发环境

由于我们客户端大多是给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
相关推荐
Johny_Zhao1 小时前
Docker + CentOS 部署 Zookeeper 集群 + Kubernetes Operator 自动化运维方案
linux·网络安全·docker·信息安全·zookeeper·kubernetes·云计算·系统运维
小毛驴8502 小时前
Linux 后台启动java jar 程序 nohup java -jar
java·linux·jar
好好学习啊天天向上3 小时前
世上最全:ubuntu 上及天河超算上源码编译llvm遇到的坑,cmake,ninja完整过程
linux·运维·ubuntu·自动性能优化
tan180°4 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
典学长编程4 小时前
Linux操作系统从入门到精通!第二天(命令行)
linux·运维·chrome
wuk9984 小时前
基于MATLAB编制的锂离子电池伪二维模型
linux·windows·github
彭祥.5 小时前
Jetson边缘计算主板:Ubuntu 环境配置 CUDA 与 cudNN 推理环境 + OpenCV 与 C++ 进行目标分类
c++·opencv·分类
lzb_kkk5 小时前
【C++】C++四种类型转换操作符详解
开发语言·c++·windows·1024程序员节
独行soc7 小时前
#渗透测试#批量漏洞挖掘#HSC Mailinspector 任意文件读取漏洞(CVE-2024-34470)
linux·科技·安全·网络安全·面试·渗透测试
BD_Marathon7 小时前
Ubuntu下Tomcat的配置
linux·ubuntu·tomcat