【云备份】文件操作实用工具类设计
文章目录
- 为什么要单独设计文件工具类?
- 整体实现
- Filesize ——文件大小
- stat接口
- LastMTime ——最后一次修改时间
- LastATime —— 最后一次访问时间
- FileName —— 文件名称
- GetPostLen ——获取文件指定位置 指定长度的数据
- GetContnet —— 读取文件数据
- SetContent ——向文件中写入数据
- Compress —— 压缩
- UnCompress —— 解压缩
- firesystem手册使用
- Exists—— 判断文件是否存在
- CreateDirectory ——创建目录
- ScanDirectory ——返回指定文件夹中所有的文件路径名称
- 整体代码
- util.hpp
- makefile
- cloud.cpp (测试代码)
为什么要单独设计文件工具类?
由于在客户端和服务器端中 都涉及到文件的读写
所以要先设计 封装文件操作类,当该类设计好后 对文件的操作时就会变的简单化

功能:
1. Filesize 获取文件的大小
2. LastModTime 获取文件最后一次修改时间
3. LastAccessTime 获取文件最后一次访问时间
4. FileName 获取文件路径名中的文件名称
5. SetContent 向文件中写入数据
6. GetContnet 读取文件数据
7. GetPostLen 获取文件指定位置 指定长度的数据
8. GetDirectory 返回指定文件夹中所有的文件路径名称
9. Exists 判断文件是否存在,若不存在则创建
10. CreateDirectory 创建目录
11. Compress 文件压缩
12. Uncompress 文件解压缩
整体实现

创建一个 util.hpp
在其内部 创建一个 cloud 命名空间
在cloud中,创建一个FileUtil类
在私有权限中,设置一个 _filename 整体文件名称(可能包含文件路径)
Filesize ——文件大小
stat接口

stat 通过文件的路径名称访问文件,获取文件的状态属性信息,再放入到buf中
若返回小于0,则表示访问失败

stat结构体中包含的属性最主要的有
st_size(文件大小)
st_atime(文件最后一次访问时间)
st_mtime(文件最后一次修改时间)

若访问文件失败,则打印 get file size failed
若访问成功,则返回 stat类型结构体 的 st_size 即可 表示 文件大小
LastMTime ——最后一次修改时间

同样使用stat函数,若返回值小于0则说明访问失败 返回 get fire size faied
若访问成功,则 返回 stat结构体的 st_mtime 即可 表示 文件最后一次修改时间
LastATime —— 最后一次访问时间

使用stat函数,若返回值小于0则说明访问失败 返回 get fire size faied
若访问成功,则 返回 stat结构体的 st_atime 即可 表示 文件最后一次访问时间
FileName —— 文件名称
路径之间都是以 / 来进行间隔的
所以只需找到最后一个 / ,从该/ 开始的下一个位置开始 就是文件名的起始位置
string 中的 find_last_of()函数可以用来查找某个字符最后一次出现的位置

若没有找到 / ,则表示 filename 就为 文件名称
若找到/ ,则从 /的下一个位置开始截断 直到 文件末尾 , 将子串整体作为文件名称返回
GetPostLen ——获取文件指定位置 指定长度的数据

获取文件是要从文件中读取数据 所以使用 ifstream 类型
ios::binary 表示 二进制
所以 以二进制的形式打开 _filename 文件
若打开文件失败,则打印 open file failed

若打开文件成功,还需判断下pos位置 是否超过 文件的整体大小
若超过文件整体大小,则 返回 false

使用 seekg 跳转到文件pos位置
调整body的大小为 文件大小len
将文件数据放入 body中
若读取出错,则返回false

GetContnet —— 读取文件数据

先通过FileSize 获取文件大小
再通过调用 GetPostLen 函数 即可读取到整个文件的数据
SetContent ——向文件中写入数据

写入文件数据 就为输入 所以使用 ofstream 类型
使用 二进制的方式打开文件 filename
打开失败,则返回false

将body数据写入到文件中
若写入失败,则返回false

Compress —— 压缩

将filename的文件内容 全部读取到 body中
若读取失败,则返回 false

选择 LZIP 压缩格式,body作为文件内容,使用 pack 进行压缩,返回值就是压缩之后的数据

通过packname实例化一个新对象 fu
再将 压缩的数据 packed 读取到文件中
若写入失败,则返回false
若写入成功,则返回true

UnCompress —— 解压缩

将filename的文件内容 全部读取到 body中
若读取失败,则返回 false

将body中的文件内容进行解压缩

通过filename实例化一个新对象 fu
再将 解压缩的数据 unpacked 读取到文件中
若写入失败,则返回false
若写入成功,则返回true

firesystem手册使用
在C++17中 支持的一个文件系统 filesystem 完成目录的遍历操作
点击查看:firesystem手册地址
打开文档后 向下翻

找到 create_directory 创建目录(单层级)
create_directories 创建目录(多层级)

只需传入目录的路径名即可

exists 文件是否存在

将文件名传入即可

遍历目录的迭代器 directory_iterator
Exists—— 判断文件是否存在

fs作为文件系统的命名空间

调用 filesystem手册中的 exists 接口 传入文件名 即可达到 判断文件是否存在的作用
CreateDirectory ——创建目录

如果不存在就创建,如果存在就不需要创建了
调用 filesystem手册中的 create_directories 接口 传入目录的路径名 即可达到 创建目录的作用
ScanDirectory ——返回指定文件夹中所有的文件路径名称

需要先判断,在遍历的过程中,是否为文件,若不为文件,则不进行操作

借助firesystem手册中的 is_directory 作用为 判断是否是一个目录

将文件名传入即可

迭代器的返回数据 不是一个 string 类型
所以当要添加文件时 不能直接向arry中添加 p

借助firesystem手册中的 path 类 进行实例化 一个path对象

想要返回文件的相对路径 ,所以借助path类中的 relative_path
最终为 获取带有路径的文件名 中的 string 对象

整体代码
util.hpp
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<sys/stat.h>
#include"bundle.h"
#include<experimental/filesystem>namespace cloud
{namespace fs=std::experimental::filesystem;class FileUtil{private:std::string _filename;//文件名称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!\n"; return -1;}return st.st_size; }time_t LastMTime()//文件最后一次修改时间{struct stat st;if( stat(_filename.c_str(),&st)<0){std::cout<<"get file size failed!\n";return -1;} return st.st_mtime; }time_t LastATime()//文件最后一次访问时间{struct stat st;if( stat(_filename.c_str(),&st)<0){std::cout<<"get file size failed!\n";return -1;}return st.st_atime;}std::string FileName()//文件名称{// ./abc/test.txtsize_t pos=_filename.find_last_of("/");if(pos==std::string::npos){return _filename;}return _filename.substr(pos+1);}bool GetPostLen(std:: string *body,size_t pos,size_t len)//获取文件数据{std::ifstream ifs;ifs.open(_filename,std::ios::binary);//以二进制方式打开文件if(ifs.is_open()==false){std::cout<<"read file failed"<<std::endl;return false;}//打开成功,获取文件数据size_t fsize=this->FileSize();//获取文件大小if(pos+len>fsize)//若pos开始位置超过了文件大小{std::cout<<"get file len is error"<<std::endl;return false;}ifs.seekg(pos,std::ios::beg);//从文件起始位置偏移到pos位置处body->resize(len);ifs.read(&(*body)[0], len);//读取文件所有数据到 body中if(ifs.good()==false)//读取出错{std::cout<< "get file content fialed "<<std::endl;ifs.close();return false;}ifs.close();return true;}bool GetContent(std::string *body) //获取整体文件数据{size_t fsize=this->FileSize();//获取文件大小return GetPostLen(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());//将body数据写入到文件中if(ofs.good()==false)//写入失败{std::cout<<"write file content failed"<<std::endl;ofs.close(); return false;}ofs.close();return true;}bool compress(const std::string &packname) //压缩{//读取文件数据std::string body;if(this->GetContent(&body)==false){std::cout<<"compress get file content failed"<<std::endl;return false;} //对数据进行压缩std::string packed=bundle::pack(bundle::LZIP,body);//将压缩数据存储到压缩包文件中FileUtil fu(packname);if(fu.Setcontent(packed)==false)//写入数据失败{std::cout<<"compress write packed data failed"<<std::endl;return false;}return true;}bool UnCompress(const std::string &filename)//解压缩{//将当前压缩包数据读取出来std::string body;if(this->GetContent(&body)==false)//获取文件内容{std::cout<<"compress get file content failed"<<std::endl;return false;} //对压缩的数据进行解压缩std::string unpacked=bundle::unpack(body);//将解压缩的数据写入到新文件中FileUtil fu(filename);if(fu.Setcontent(unpacked)==false)//写入数据失败{std::cout<<"uncompress write packed data failed"<<std::endl;return false;}return true;}bool Exists()//判断文件是否存在{return fs::exists(_filename);}bool CreateDirectory()//创建目录{if(this->Exists()){return true;}return fs::create_directories(_filename);}bool ScanDirectory(std::vector<std::string> * arry)//浏览目录{for (auto & p : fs::directory_iterator(_filename))//遍历目录{if(fs::is_directory(p)==true)//检测遍历到的文件 是一个文件夹 就不进行操作{continue;}//普通文件才进行操作//relative_path 表示带有路径的文件名arry->push_back(fs::path(p).relative_path().string());}return true;}};
}
makefile
cloud:cloud.cpp util.hpp bundle.cppg++ $^ -o $@ -lpthread -lstdc++fs
.PHONY:clean
clean:rm -f cloud
cloud.cpp (测试代码)
#include"util.hpp"void FileUtilTest(const std::string &filename){/*1.cloud::FileUtil fu(filename);std::cout<<fu.FileSize() <<std::endl;std::cout<<fu.LastMTime()<<std::endl;std::cout<<fu.LastATime()<<std::endl;std::cout<<fu.FileName() <<std::endl;2.// 将 filename 文件内容 全部读取到 body中cloud::FileUtil fu(filename);std::string body;fu.GetContent(&body);//读取文件数据//再将body中的数据内容 读取到文件中cloud::FileUtil nfu("./hello.txt");nfu.Setcontent(body); //将body写入文件中return;3.//将packname数据进行压缩 再将其进行解压 放入 hello.txt中std::string packname=filename +".lz";cloud::FileUtil fu(filename);fu.compress( packname);//将压缩的数据放入packname中cloud::FileUtil pfu( packname);pfu.UnCompress("./hello.txt");//将packname中的数据放入 hello.txt中return;*/cloud::FileUtil fu(filename);fu.CreateDirectory();//创建目录std::vector<std::string>arry;fu.ScanDirectory(&arry);//浏览目录for(auto &a: arry){std::cout<<a<<std::endl;}return;
} int main(int argc,char*argv[]){FileUtilTest(argv[1]); return 0;}
相关文章:

【云备份】文件操作实用工具类设计
文章目录 为什么要单独设计文件工具类?整体实现Filesize ——文件大小stat接口 LastMTime ——最后一次修改时间LastATime —— 最后一次访问时间FileName —— 文件名称GetPostLen ——获取文件指定位置 指定长度的数据GetContnet —— 读取文件数据SetContent ——…...
LeetCode Hot100 199.二叉树的右视图
题目: 给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 方法(灵神):先递归右子树,再递归左子树,在递归的同…...

Nacos身份绕过漏洞复现(QVD-2023-6271)
Nacos身份绕过漏洞复现(QVD-2023-6271) 环境配置 该漏洞主要用了win10_JAVA的环境,参考网上已有的复现文章,使用jdk-11.0.2_windows-x64_bin.exe 由于2.2.0之后的nacos已将本漏洞修复,所以本次复现使用2.2.0的包 下…...

Elasticsearch集群部署 head监控插件 Kibana部署 Nginx反向代理 Logstash部署
一、组件介绍1、Elasticsearch:2 、Logstash3、Kibana4、Kafka:5、Filebeat: 二、 Elasticsearch集群部署服务器创建用户安装ES修改配置文件创建数据和日志目录设置JVM堆大小 #7.0默认为4G修改安装目录及存储目录权限系统优化(1)增…...

网络和Linux网络_5(应用层)HTTP协议(方法+报头+状态码)
目录 1. HTTP协议介绍 1.1 URL介绍 1.2 urlencode和urldecode 1.3 HTTP协议格式 1.4 HTTP的方法和报头和状态码 2. 代码验证HTTP协议格式 HttpServer.hpp 2.2 html正式测试 Util.hpp index.html 2.3 再看HTTP方法和报头和状态码 2.3.1 方法_GET和POST等 2.3.2 报头…...
人工智能-注意力机制之残差连接和层规范化
残差连接和层规范化 层规范化和批量规范化的目标相同,但层规范化是基于特征维度进行规范化。尽管批量规范化在计算机视觉中被广泛应用,但在自然语言处理任务中(输入通常是变长序列)批量规范化通常不如层规范化的效果好。 以下代…...
linux centos安装nvm
安装目录 mkdir /opt/nvm && cd /opt/nvm安装包下载 wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.39.5.tar.gz注意:https://github.com/nvm-sh/nvm/tags获取新版本或所需版本下载链接并替换 安装包解压 for file in *.tar.gz; do tar -zxv…...

Spring(2):Spring事务管理机制
Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的: PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理。TransactionDefinition: 事务定义信息(隔离、传播、超时、只读)—通过配置如…...

STK Components 二次开发-创建卫星
1.卫星数据 可以用stk 里面自带的 参数帮助文档。 也可以自己下载 CelesTrak: Current GP Element Sets 这里你所需要的最新卫星数据全有。 其实创建需要的就是卫星的二根数。 给定二根数也可以。 读取数据库中的卫星数据 这个接口优先下载最新的。 var tleList TwoL…...

【深度学习】因果推断与机器学习的高级实践 | 数学建模
文章目录 因果推断因果推断的前世今生(1)潜在结果框架(Potential Outcome Framework)(2)结构因果模型(Structual Causal Model,SCM) 身处人工智能爆发式增长时代的机器学…...
【华为OD】B\C卷真题 100%通过:字符串统计 C/C++实现
目录 题目描述: 示例1 代码实现: 【华为OD】B\C卷真题 100%通过:字符串统计 C/C实现 题目描述: 给定两个字符集合,一个为全量字符集,一个为已占用字符集。已占用的字符集中的字符不能再使用,要求输出剩…...
SparkSession介绍
一、 介绍 SparkSession是Spark 2.0中引入的新概念,它是Spark SQL、DataFrame和Dataset API的入口点,是Spark编程的统一API,也可看作是读取数据的统一入口;它将以前的SparkContext、SQLContext和HiveContext组合在一起࿰…...

Error PostCSS plugin autoprefixer requires PostCSS 8
文章目录 一、情况一二、情况二三、总结 在启动 vue项目时,突然控制台报错: Error: PostCSS plugin autoprefixer requires PostCSS 8。然后依次出现下面几种情况,依次解决完,项目就可以正常启动了 一、情况一 error in ./src/…...

纵观手机市场,手机即鏖战全面屏
9月13日,在相继发布Apple TV、Apple Watch 和iPhone 8/8 Plus之后,当大家都以为苹果新品发布会临近结束之时,苹果前CEO史蒂夫乔布斯的这句经典名言再现屏幕,iPhone X终于揭开了神秘面纱。 “One more thing”。 9月13日ÿ…...

基于C#实现Dijkstra算法
或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划”这些经典策略,当然有的问题我们可以用贪心来寻求整体最优解࿰…...

【数据结构】树与二叉树(廿三):树和森林的遍历——层次遍历(LevelOrder)
文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法5.3.3 树和森林的遍历1. 先根遍历(递归、非递归)2. 后根遍历(递归、非递归)3. 森林的遍历4. 层次遍历a. 算法LevelOrderb. 算法解读c. 时间复杂度d.代码…...
常用连接池的使用(jdbc)java 连接数据库
C3P0 导入依赖 <!-- https://mvnrepository.com/artifact/c3p0/c3p0 --><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency><!-- https://mvnrepository.c…...

linux嵌入式时区问题
目录 操作说明实验参考 最近有个针对时区的需求,研究了下。 查询网上的一些设置,发现基本都是系统中自带的一些文件,然后开机时解析,或者是有个修改的命令。 操作 但针对嵌入式常用到的 busybox 制作的最小系统,并没…...
Spring基于xml注入bean的几种方式; Spring 框架中都用到了哪些设计模式;Spring的自动装配
文章目录 Spring基于xml注入bean的几种方式:Spring的自动装配:在Spring框架xml配置中共有5种自动装配:基于注解的方式: Spring 框架中都用到了哪些设计模式? Spring基于xml注入bean的几种方式: ࿰…...

name 属性:提高 Vue 应用可维护性的关键
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...