【云备份】文件操作实用工具类设计

文章目录

  • 为什么要单独设计文件工具类?
  • 整体实现
    • 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;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/170286.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算领域的第三代浪潮!

根据IDC不久前公布的数据&#xff0c;2023年上半年中国公有云服务整体市场规模(IaaS/PaaS/SaaS)为190.1亿美元&#xff0c;阿里云IaaS、PaaS市场份额分别为29.9%和27.9%&#xff0c;都远超第二名&#xff0c;是无可置疑的行业领头羊。 随着人工智能&#xff08;AI&#xff09;…

cmake install接口常用方式介绍

cmake install接口常用方式介绍 1 Synopsis2 Introduction2.1 DESTINATION <dir>2.2 PERMISSIONS <permission>...2.3 CONFIGURATIONS <config>...2.4 COMPONENT <component>2.5 EXCLUDE_FROM_ALL2.6 RENAME <name>2.7 OPTIONAL 3 Signatures4 E…

走近科学之《MySQL 的秘密》

走近科学之《MySQL 的秘密》 mysql 存储引擎、索引、执行计划、事务、锁、分库分表、优化 1、存储引擎&#xff08;storage engines&#xff09; 存储引擎规定了数据存储时的不同底层实现&#xff0c;如存储机制、索引、锁、事务等。 可以通过 show engines 命令查看当前服务…

在 STM32 上实现温度补偿和校正

本文介绍了如何在 STM32 微控制器上实现温度补偿和校正&#xff0c;以提高温度传感器的测量精度。首先&#xff0c;我们将简要介绍温度补偿和校正的原理和目的。然后&#xff0c;我们将详细讨论在 STM32 上实现温度补偿和校正的步骤和方法。同时&#xff0c;提供了一个简单的示…

Android逆向实战 - MIUI调起三方应用系统拦截弹窗分析

近期&#xff0c;发现在部分Android手机调起其他应用时&#xff0c;会弹出一个系统弹窗拦截调起&#xff0c;需要用户二次确认。经过内部众测&#xff0c;发现绝大多数是小米手机&#xff0c;而且跟Android版本没有直接关系&#xff0c;猜测是MIUI某次升级引入的功能。这篇文章…

oracle的debjob挂載及查詢

背景 有一個需求需要定時去執行一個produce&#xff0c;可以使用oracle的dbjob定時執行&#xff0c;相比較之前的vbs更加絲滑 --傳遞produce 開始的時間 頻率 declarea number;beginDBMS_JOB.SUBMIT(a,xx_warehouse_daliy_record_p;,to_date(202311230800,yyyymmddhh24mi),…

illuminate/database 使用 四

文档&#xff1a;Hyperf Database: Getting Started - Laravel 10.x - The PHP Framework For Web Artisans 因为hyperf使用illuminate/database&#xff0c;所以按照文章&#xff0c;看illuminate/database代码实现。 一、读写分离 根据文档读写的host可以分开。设置读写分…

管理类联考——写作——考点+记忆篇——论证有效性分析——记忆

文章目录 论证有效性分析得分要点、寻找漏洞方法论证有效性分析五大逻辑漏洞类型论证有效性分析的具体写法论证有效性分析十大解题思路&#xff08;上&#xff09;方法一&#xff1a;理想法方法二&#xff1a;极端法方法三&#xff1a;其他因素法方法四&#xff1a;可行性法 论…

Everything进行内网穿透搜索

文章目录 1\. 部署内网穿透1.1. 注册账号1.2. 登录1.3. 创建隧道 2\. 从外网访问Everything 借助cpolar可以让我们在公网上访问到本地的电脑 1. 部署内网穿透 1.1. 注册账号 在使用之前需要先进行注册cpolar cpolar secure introspectable tunnels to localhost 1.2. 登录 C…

grdle 的安装与配置 、gradle和jdk版本对应关系

java与gradle对应的版本关系 Java Java Gradle需要Java版本在8到19之间。目前还不支持Java 20及更高版本。 Java 6和Java 7仍然可以用于编译&#xff0c;但已经不适合用于测试。Gradle 9.0不支持Java 6和Java 7的测试。任何完全支持的Java版本都可以用于编译或测试。 然而&…

Ubuntu下使用protoBuf

一、protobuf简介&#xff1a; 1.1 protobuf的定义&#xff1a; protobuf是用来干嘛的&#xff1f; protobuf是一种用于 对结构数据进行序列化的工具&#xff0c;从而实现 数据存储和交换。 &#xff08;主要用于网络通信中 收发两端进行消息交互。所谓的“结构数据”是指类…

【STM32】GPIO输出

1 GPIO简介 &#xff08;1&#xff09;GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口 &#xff08;2&#xff09;可配置为8种输入输出模式 &#xff08;3&#xff09;引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V&#xff08;可以输…

【LeetCode】挑战100天 Day15(热题+面试经典150题)

【LeetCode】挑战100天 Day15&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-172.1 题目2.2 题解 三、面试经典 150 题-173.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…

QQ空间上传一次 500张限制突破记录

手机又好多照片了&#xff0c;用手机上传耽误时间&#xff0c;就导出到电脑了&#xff0c;上传到qq空间去。 结果发现不开通黄钻无法上传原图&#xff0c;那就开通吧&#xff01; 开通了黄钻&#xff0c;居然不能一次上传超过 500 张&#xff0c;开通有何用&#xff1f; 五千…

电磁场信息论及先进MIMO (黄大年茶思屋座谈) 笔记

天线阵的负载动态调控&#xff0c;动态阻抗匹配网络&#xff0c;实时跟着扫描角度的变化而变化&#xff0c;可能突破Hannan极限。 新的天线构架&#xff1a; 周期 —》非周期 每个单元不一样 动态可调&#xff0c;可重构 每个天线多端口或多模式 多层天线 非周期结构天线的增…

vscode导入STM32CubeIDE工程文件夹未定义警告清除方法

0 前言 在我们使用vscode去编辑STM32CubeIDE的工程文件时&#xff0c;经常会出现一些类型未定义、头文件路径无效的问题&#xff0c;无法正常使用且非常影响观感。本文介绍如何设置vscode导入的STM32CubeIDE配置文件&#xff0c;解决这一问题。 1 vscode导入STM32CubeIDE工程…

从0到0.01入门 Webpack| 003.精选 Webpack面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

rocky8.9配置K8S集群kubernetes,centos同理

rocky8.9配置K8S集群 节点主机名IP地址mastertang1192.168.211.101node1tang2192.168.211.102node2tang3192.168.211.103 1&#xff09;准备工作 全部主机都配置静态ip vi /etc/sysconfig/network-scriptsTYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DE…

【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析模拟实现

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 ✏️真正相信奇迹的家伙&#xff0c;本身和奇迹一样了不起啊&#xff01; 欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;>希望看完我的文章对你有小小的帮助&am…

java学习part11继承

1.类的继承 继承为了让类之间建立联系&#xff0c;同时复用代码。 子类和父类的同名函数构成重写&#xff0c;能覆盖&#xff0c;除非用super.xx()调。 同名属性不会覆盖&#xff0c;而是并存&#xff0c;用super.xx调。 2.子类初始化 子类会自动调用父类无参构造super() 3.重…