一,客户端整体框架
客户端要实现的功能和服务端相比相对简单,客户端要实现的功能是自动对指定文件中的文件进行备份,也就是定时对指定文件进行扫描,根据文件信息判断文件,符合要求(新文件或者被修改过的文件)进行上传
因此我们客户端大概需要实现下面三个模块
- 数据管理模块:管理备份文件的文件信息,后续需要通过该信息判断文件是否上传
- 目录遍历模块:定时遍历指定文件下的所有文件
- 文件备份模块:遍历文件时,根据文件信息判断是否上传
开发环境
由于我们客户端大多是给windows用户使用的,因此客户端在Windows上用vs2019进行开发
二,实用工具类实现
客户端的实用工具类的实现和服务端是一样的,但是功能少了些,例如压缩解压缩,同时因为vs2019上按照Json库不太方便,因此Json序列化和Json反序列化也不在使用,而在数据管理模块中数据存储时用到的序列化和反序列化,由我们自己完成。
#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
文章来源地址https://www.toymoban.com/news/detail-698964.html文章来源:https://www.toymoban.com/news/detail-698964.html
到了这里,关于云备份客户端——客户端整体设计框架以及实用类工具实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!