当前位置: 首页 > news >正文

C++项目——云备份-⑧-客户端各模块实现

文章目录

  • 专栏导读
  • 1.客户端数据管理模块实现
  • 2.客户端文件检测模块实现
  • 3.客户端文件备份模块设计
  • 4.客户端文件备份模块实现

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——云备份

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux
🌸项目Gitee链接:https://gitee.com/li-yuanjiu/cloud-backup

在这里插入图片描述

1.客户端数据管理模块实现

客户端要实现的功能是对指定文件夹中的文件自动进行备份上传。但是并不是所有的文件每次都需要上传,我们需要能够判断,哪些文件需要上传,哪些不需要,因此需要将备份的文件信息给管理起来,作为下一次文件是否需要备份的判断。因此需要被管理的信息包含以下:

  • 文件路径名称
  • 文件唯一标识:由文件名,最后一次修改时间,文件大小组成的一串信息;

客户端数据管理模块可直接由服务端数据管理模块改造得到,因为其只需要服务端数据管理模块代码中一小部分功能。

#ifndef __MY_DATA__
#define __MY_DATA__
#include <unordered_map>
#include <sstream>
#include "util.hpp"namespace cloud
{class DataManager{public:DataManager(const std::string &backup_file) :_backup_file(backup_file){InitLoad();}bool Storage(){// 1.获取所有的备份信息std::stringstream ss;auto it = _table.begin();for (; it != _table.end(); ++it){// 2.将所有信息进行指定持久化格式的组织ss << it->first << " " << it->second << "\n";}// 3.持久化存储FileUtil fu(_backup_file);fu.SetContent(ss.str());return true;}bool InitLoad(){// 1.从文件中读所有数据FileUtil fu(_backup_file);std::string body;fu.GetContent(&body);// 2.进行数据解析,添加到表当中std::vector<std::string> array;Split(body, "\n", &array);for (auto& a : array){std::vector<std::string> tmp;Split(a, " ", &tmp);if (tmp.size() != 2){continue;}_table[tmp[0]] = tmp[1];}return true;}bool Insert(const std::string &key, const std::string &val){_table[key] = val;Storage();return true;}bool Updata(const std::string& key, const std::string& val){_table[key] = val;Storage();return true;}bool GetOneByKey(const std::string& key, std::string* val){auto it = _table.find(key);if (it == _table.end()){return false;}*val = it->second;return true;}private:int Split(const std::string &str, const std::string &sep, std::vector<std::string>* array){int  count = 0;size_t pos = 0, idx = 0;while (1){pos = str.find(sep, idx);if (pos == std::string::npos){break;}if (pos == idx){idx = pos + sep.size();continue;}std::string tmp = str.substr(idx, pos - idx);array->push_back(tmp);count++;idx = pos + sep.size();}if (idx < str.size()){array->push_back(str.substr(idx));count++;}return count;}private:std::string	 _backup_file; // 备份信息持久化存储文件std::unordered_map<std::string, std::string> _table;};
}
#endif

2.客户端文件检测模块实现

同样的,客户端文件实用工具类其实与服务端的文件实用工具类雷同,只是功能需求并没有服务端那么多,复制过来即可。

#ifndef __MY_UTIL__
#define __MY_UTIL__
/*1.获取文件大小2.获取文件最后一次修改时间3.获取文件最后一次访问时间4.获取文件路径名中的文件名称 /abc/test.txt -> test.txt5.向文件写入数据6.获取文件数据7.获取文件指定位置 指定数据长度8.判断文件是否存在9.创建目录10.浏览获取目录下的所有文件路径名11.压缩文件12.解压缩所有文件
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <experimental/filesystem>
#include <sys/stat.h>namespace cloud
{namespace fs = std::experimental::filesystem;class FileUtil{public:FileUtil(const std::string &filename) :_filename(filename){}int64_t FileSize(){struct stat st;if(stat(_filename.c_str(), &st) < 0){std::cout << "get file size failed!" << std::endl;return 0;}return st.st_size;}time_t LastMTime(){struct stat st;if(stat(_filename.c_str(), &st) < 0){std::cout << "get last modify time 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 last access time failed!" << std::endl;return -1;}return st.st_atime;  }std::string FileName(){size_t pos = _filename.find_last_of("/");if(pos == std::string::npos){return _filename;}return _filename.substr(pos+1);}bool GetPosLen(std::string *body, size_t pos, size_t len){size_t fsize = FileSize();if(pos + len > fsize){std::cout << "get file len error" << std::endl;return false;}std::ifstream ifs;ifs.open(_filename, std::ios::binary);if(ifs.is_open() == false){std::cout << "open file failed!" << std::endl;return false;}ifs.seekg(pos, std::ios::beg);body->resize(len);ifs.read(&(*body)[0], len);if(ifs.good() == false){std::cout << "get file content failed" << std::endl;ifs.close();return false;}ifs.close();return true;}bool GetContent(std::string *body){size_t fsize = FileSize();return GetPosLen(body, 0, fsize);}bool SetContent(const std::string &body){std::ofstream ofs;ofs.open(_filename, std::ios::binary);if(ofs.is_open() == false){std::cout << "write open file failed" << std::endl;return false;}ofs.write(&body[0], body.size());if(ofs.good() == false){std::cout << "write open file failed" << std::endl;ofs.close();return false;}ofs.close();return true;}bool Exists(){return fs::exists(_filename);}bool Remove(){if(Exists() == false){return true;}remove(_filename.c_str());return true;}bool CreateDirectory(){if(Exists()) return true;return fs::create_directories(_filename);}bool ScanDirectory(std::vector<std::string> *array){CreateDirectory();for(auto& p : fs::directory_iterator(_filename)){if(fs::is_directory(p) == true) continue;// relative_path 带有路径的文件名array->push_back(fs::path(p).relative_path().string());}return true;}private:std::string _filename;};
}
#endif

3.客户端文件备份模块设计

回顾客户端自动将指定文件夹中的文件备份到服务器流程:

  • 遍历指定文件夹
  • 逐一判断文件是否需要备份
  • 需要备份的文件进行上传备份

客户端文件备份类主要包含以下成员:

#define SERVER_ADDR "47.108.25.253" // 服务器IP
#define SERVER_PORT 8989 // 服务器端口
class Backup
{
public:Backup(const std::string& back_dir, const std::string& back_file);// 生成文件的唯一标识std::string GetFileIdentifier(std::string filename);// 上传文件函数bool Upload(const std::string& filename); // 判断是否需要上传bool IsNeedUpload(const std::string& filename);// 主逻辑执行函数bool RunMoudle();
private:std::string _back_dir; // 监控的文件目录DataManager* _data;
};

4.客户端文件备份模块实现

#ifndef __MY_CLOUD__
#define __MY_CLOUD__
#include "data.hpp"
#include "httplib.h"
#include <Windows.h>
#define SERVER_ADDR "47.108.25.253"
#define SERVER_PORT 8989
namespace cloud
{class Backup{public:Backup(const std::string& back_dir, const std::string& back_file):_back_dir(back_dir){_data = new DataManager(back_file);}std::string GetFileIdentifier(std::string filename){FileUtil fu(filename);std::stringstream ss;ss << fu.FileName() << "-" << fu.FileSize() << "-" << fu.LastMTime();return ss.str();}bool Upload(const std::string& filename){// 1.获取文件数据FileUtil fu(filename);std::string body;fu.GetContent(&body);// 2.搭建http客户端上传文件数据httplib::Client client(SERVER_ADDR, SERVER_PORT);httplib::MultipartFormData item;item.content = body;item.filename = fu.FileName();item.content_type = "application/octet-stream";httplib::MultipartFormDataItems items;items.push_back(item);auto res = client.Post("/upload", items);if (!res || res->status != 200){return false;}return true;}bool IsNeedUpload(const std::string& filename){// 需要上传的文件判断条件:文件是新增的,不是新增的但是被修改过// 文件是新增的:看一下有没有备份信息// 不是新增的但是被修改过:有历史信息,但是历史信息的唯一标识符与当前最新的唯一标识符不一致std::string id;if (_data->GetOneByKey(filename, &id) != false){// 有历史信息std::string new_id = GetFileIdentifier(filename);if (new_id != id){return false;}}//判断一个文件是否有一段时间没有被修改过了FileUtil fu(filename);if (time(NULL) - fu.LastMTime() < 3){return false;}return true;}bool RunMoudle(){while (1){// 1.遍历获取指定文件夹中所有文件FileUtil fu(_back_dir);std::vector<std::string> array;fu.ScanDirectory(&array);// 2.逐个判断是否需要上传for (auto& a : array){if (IsNeedUpload(a) == false)continue;// 3.如果需要,则上传文件if (Upload(a) == true){_data->Insert(a, GetFileIdentifier(a));}}Sleep(1);}}private:std::string _back_dir;DataManager* _data;};
}
#endif

在这里插入图片描述

相关文章:

C++项目——云备份-⑧-客户端各模块实现

文章目录 专栏导读1.客户端数据管理模块实现2.客户端文件检测模块实现3.客户端文件备份模块设计4.客户端文件备份模块实现 专栏导读 &#x1f338;作者简介&#xff1a;花想云 &#xff0c;在读本科生一枚&#xff0c;C/C领域新星创作者&#xff0c;新星计划导师&#xff0c;阿…...

分享一款基于 AI 的 Chrome 插件

最近使用大模型比较多&#xff0c;公司虽然提供了免费的 ChatGPT 但是需要跳转特定页面才能访问&#xff0c;比较麻烦&#xff0c;于是就想到是否可以开发一款类似于有道词典一样的 Chrome 插件&#xff0c;可以在任意页面使用&#xff0c;虽然市面上也有类似的插件&#xff0c…...

Spring Authorization Server 1.1 扩展实现 OAuth2 密码模式与 Spring Cloud 的整合实战

目录 前言无图无真相创建数据库授权服务器maven 依赖application.yml授权服务器配置AuthorizationServierConfigDefaultSecutiryConfig 密码模式扩展PasswordAuthenticationTokenPasswordAuthenticationConverterPasswordAuthenticationProvider JWT 自定义字段自定义认证响应认…...

第二证券:AIGC概念活跃,焦点科技、三维通信涨停,万兴科技大涨

AIGC概念24日盘中走势生动&#xff0c;到发稿&#xff0c;万兴科技、三态股份涨超10%&#xff0c;焦点科技、三维通讯、我国科传等涨停&#xff0c;中文在线涨超9%&#xff0c;果麦文明、新国都涨约7%。 消息面上&#xff0c;各大电商途径于10月18-24日先后发动“双11”大促或…...

7-4、S加减速转动实现【51单片机控制步进电机-TB6600系列】

摘要&#xff1a;本节介绍实现步进电机S曲线运动的代码 一、目标功能 实现步进电机转动总角度720&#xff0c;其中加减速各90 加速段&#xff1a;加速类型&#xff1a;S曲线   加速角度&#xff1a;角度为90   起步速度&#xff1a;30RPM&#xff0c;   终止速度&#x…...

RK3568-pcie接口

pcie接口与sata接口 pcie总线pcie总线pcie控制器sata控制器nvme设备sata设备nvme协议ahci协议m-key接口b-key接口RC模式和EP模式 RC和EP分别对应主模式和从模式,普通的PCI RC主模式可以用于连接PCI-E以太网芯片或PCI-E的硬盘等外设。 RC模式使用外设一般都有LINUX驱动程序,安…...

spring监听请求执行结束,移除当前ThreadLocal数据两种方法

在开发过程中&#xff0c;很多时候我们会使用ThreadLocal来临时缓存数据&#xff0c;当一次数据请求执行完成后需要主动执行释放当前ThreadLocal缓存数据资源&#xff0c;防止未能及时释放导致下一次访问时候ThreadLocal依然保持上一次缓存的数据。 spring提供两种方式去监听一…...

知识图谱--Jena基础操作和检索推理应用

在上一篇读书笔记中讲到知识图谱存储主要有基于开源的Jena方式和基于图数据库(Neo4j)方式,本次主要对Jena的基础操作和如何应用进行了实践总结,同时结合了D2R,将结构化数据转换成Jena可以加载的格式(即RDF,后缀是.nt),Apache Jena作为一种开源的Java语义网框架,主要功…...

GEE python——将GEE ASSETS中存储的影像或者矢量转化为数据格式XEE()

数据转换器是内置于 getPixels、computePixels、listFeatures 和 computeFeatures 中的客户端转换能力。通过指定兼容的文件格式,这些方法可以返回 Python 原生格式的数据,如用于栅格的结构化 NumPy 数组和用于矢量的 Pandas DataFrames 或 GeoPandas GeoDataFrames。对于矢量…...

Java集合框架:List、Set、Map类型及泛型详解

文章目录 &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。&#x1f30e;跑过十五…...

Ubuntu 安装 docker

一.添加Docker官方GPG密钥 curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - 如果出现&#xff1a; The program curl is currently not installed. You can install it by typing: sudo apt install curl 先安装 curl : sudo apt inst…...

BUUCTF zip伪加密 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 下载附件&#xff0c;得到一个zip压缩包。 密文&#xff1a; 解题思路&#xff1a; 1、刚开始尝试解压&#xff0c;看到了flag.txt文件&#xff0c;但需要解压密码。结合题目&#xff0c;确认这是zip伪加密&#…...

p5.js 到底怎么设置背景图?

本文简介 点赞 关注 收藏 学会了 在 《p5.js 光速入门》 里我们学过加载图片元素&#xff0c;学过过背景色的用法&#xff0c;但当时没提到背景图要怎么使用。 本文就把背景图这部分内容补充完整&#xff0c;并且会提到在 p5.js 里使用背景图的一些注意点。 背景图的用法…...

python+unittest+requests+HTMLRunner编写接口自动化测试集

问题描述&#xff1a; 搭建接口测试框架&#xff0c;执行用例请求多个不同请求方式的接口 实现步骤&#xff1a; ① 创建配置文件config.ini&#xff0c;写入部分公用参数&#xff0c;如接口的基本url、测试报告文件路径、测试数据文件路径等配置项 1 [DATABASE] 2 data_addre…...

Vue---监听div元素宽高改变时echart图表重新resize

一、需求描述 当点击上图的红色框时&#xff0c;echart的div元素宽会改变但是无法触发echarts图表的resize重新渲染&#xff0c;对于浏览器而言&#xff0c;浏览器具有window.resize方法监听浏览器窗口大小的改变&#xff0c;而div元素没有监听宽高改变的方法。 二、解决方案 …...

Kubernetes Etcd不可用日志:NOSPACE 的问题修复

两套k8s集群同一天同时出现etcd集群空间超过配额&#xff0c;kubectl get cs时发现所有的etcd均返回503报错&#xff0c;查看etcd的告警发现有NO SPACE的信息且 etcdctl --endpoints${ETCD_ENDPOINT} --cert${ETCD_CERTFILE} --key${ETCD_KEYFILE} --cacert${ETCD_CAFILE} endp…...

分组卷积的思想神了

大家好啊&#xff0c;我是董董灿。 最近&#xff0c;分组卷积帮我解决了一个大忙&#xff0c;事情是这样的。 这几天遇到一个头疼的问题&#xff0c;就是要在某一芯片上完成一个神经网络的适配&#xff0c;这个神经网络中卷积居多&#xff0c;并且有一些卷积的通道数很大&…...

北邮22级信通院数电:Verilog-FPGA(7)第七周实验(2):BCD七段显示译码器(关注我的uu们加群咯~)

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 关注作者的uu们可以进群啦~ 一.verilog代码 1.1 …...

LVS集群-DR模式

概念&#xff1a; LVS-DR模式&#xff0c;也是最常用的lVS负载方式&#xff0c;DR DIRECT ROUTING 直接路由模式 负载均衡器lVS调度器&#xff0c;只负责请求和转发到后端的真实服务器&#xff0c;但是影响结果&#xff0c;由后端服务器直接转发给客户端&#xff0c;不需要经…...

行为型模式-状态模式

在状态模式中&#xff0c;类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。 在状态模式中&#xff0c;我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。 意图&#xff1a;允许对象在内部状态发生改变时改变它的行为&#xff0…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...