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

文章目录

  • 为什么要单独设计文件工具类?
  • 整体实现
    • 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.txt
            size_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.cpp
	g++ $^ -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;
  }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 Linux 中重命名文件和目录

目录 前言 使用 mv 命令重命名文件和目录 通过组合 mv、find 和 exec 命令重命名与某个模式匹配的多个文件 使用 rename 命令轻松重命名多个文件 总结 前言 在这篇基本命令行教程中&#xff0c;你将学习在 Linux 终端重命名文件和目录的各种方法。 如何在 Linux 终端中重命…

Sublime Text 3 安装离线插件 anaconda

1 下载 Sublime Text 3 免安装版 Download - Sublime Text 2 下载 Package Control&#xff0c;放到 Sublime Text Build 3211\Data\Installed Packages 目录下。 Installation - Package Control 3 页面搜索 anaconda anaconda - Search - Package Control Anaconda - Pac…

彩纸屋在线少儿编程源码/scratch在线编程系统/培训管理系统源码/在线培训系统源码PHP

源码简介&#xff1a; 彩纸屋在线少儿编程源码&#xff0c;它是scratch在线编程系统&#xff0c;作为培训管理系统源码/在线培训系统源码&#xff0c;采用PHP源码。 彩纸屋是全国首家提供scratch开源定制和少儿编程培训管理系统源代码的服务商&#xff0c;彩纸屋提供的scratc…

WebGL/threeJS面试题扫描与总结

什么是 WebGL&#xff1f;什么是 Three.js&#xff1f;请解释three.js中的WebGL和Canvas的区别&#xff1f; WebGL(全写Web Graphics Library)是一种3D绘图协议&#xff0c;这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起&#xff0c;通过增加OpenGL ES 2.0的一个…

WordPress安装AWS插件实现文本转语音功能

适用于 WordPress 的 AWS 插件示例演示了内容创建者如何轻松地为所有书面内容添加文本转语音功能。随着语音搜索的不断增加&#xff0c;以音频格式提供更多网站内容变得至关重要。通过添加语音功能&#xff0c;网站访客可以通过在线音频播放器和播客应用程序等新渠道使用您的内…

单调栈 模板

class Solution { public: //从后往前的方法 vector<int> dailyTemperatures(vector<int>& temperatures) {int n temperatures.size();vector<int> ans(n);//创建一个大小为n的数组stack<int> st;//这个时候栈中没有任何元素for(int i n-1;i &g…

4面试题--数据库(mysql)

执⾏⼀条 select / update 语句&#xff0c;在 MySQL 中发⽣了什么&#xff1f; Server 层负责建⽴连接、分析和执⾏ SQL。MySQL ⼤多数的核⼼功能模块都在这实现&#xff0c;主要包括 连接器&#xff0c;查询缓存&#xff08;8.0版本去除&#xff0c;因为每次更新将会清空该…

使用 STM32 读取和解析 NTC 热敏电阻的数值

本文介绍了如何利用 STM32 微控制器读取和解析 NTC&#xff08;Negative Temperature Coefficient&#xff09;热敏电阻的数值。首先&#xff0c;我们将简要介绍 NTC 热敏电阻的原理和特性。接下来&#xff0c;我们将详细讨论如何设计电路连接和采用合适的 STM32 外设进行数值读…

如何在GO中写出准确的基准测试

一般来说&#xff0c;我们不应该对性能进行猜测。在编写优化时&#xff0c;会有许多因素可能起作用&#xff0c;即使我们对结果有很强的看法&#xff0c;测试它们很少是一个坏主意。然而&#xff0c;编写基准测试并不简单。很容易编写不准确的基准测试&#xff0c;并且基于这些…

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

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

机器学习算法——主成分分析(PCA)

目录 1. 主体思想2. 算法流程3. 代码实践 1. 主体思想 主成分分析&#xff08;Principal Component Analysis&#xff09;常用于实现数据降维&#xff0c;它通过线性变换将高维数据映射到低维空间&#xff0c;使得映射后的数据具有最大的方差。主成分可以理解成数据集中的特征…

JDK源码系列:StringBuffer与StringBuilder对比

一、源码分析StringBuffer与StringBuilder的区别 1、StringBuffer是多线程安全的&#xff0c;StringBuilder是多线程不安全的 多线程安全指的是 多个线程同时对一个对象进行append 等操作&#xff0c;不会出现覆盖、丢失的情况。 看下StringBuffer是如何做到多线程安全的&#…

思维模型 波纹效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。小变化&#xff0c;大影响。 1 波纹效应的应用 1.1 波纹效应在市场中的应用 2008 年&#xff0c;美国金融危机爆发&#xff0c;导致全球经济陷入衰退。这场危机的起因是美国房地产市场的崩…

一篇文章完成Hbase入门

文章目录 一、简介1、数据模型结构2、物理存储结构3、数据模型4、基本架构 二、安装1、下载解压安装包2、修改配置文件3、启动服务(单机、集群)4、配置高可用(HA) 三、命令行操作1、建表2、新增/更新数据3、查看表数据4、删除数据5、修改默认保存的数据版本 四、架构1、RegionS…

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

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

FPGA模块——SPI协议(读写FLASH)

FPGA模块——SPI协议&#xff08;读写FLASH&#xff09; &#xff08;1&#xff09;FLASH芯片 W25Q16BV&#xff08;2&#xff09;SPI协议&#xff08;3&#xff09;芯片部分命令1.Write Enable&#xff08;06h&#xff09;2.Chip Erase (C7h / 60h)3.写指令&#xff08;02h&am…

华为ospf路由协议防环和次优路径中一些难点问题分析

第一种情况是ar3的/0/0/2口和ar4的0/0/2口发布在区域1时&#xff0c;当ar1连接ar2的线断了以后&#xff0c;骨干区域就断了&#xff0c;1.1.1.1到2.2.2.2就断了&#xff0c;ping不通了。但ar5和ar6可以ping通2.2.2.2和1.1.1.1&#xff0c;ar3和ar4不可以ping通2.2.2.2和1.1.1.1…

中伟视界:AI智能分析盒子实现全方位人车监测,保障管道安全

在油气管道长又无人的场景下&#xff0c;人和车的监测问题一直是一个难题。传统的监测手段往往存在盲区和误报问题&#xff0c;给管道运行安全带来了一定的隐患。然而&#xff0c;随着人工智能技术的不断发展&#xff0c;利用AI盒子的智能分析算法可以有效解决这一问题。 首先&…

【从浅识到熟知Linux】基本指定之cat、more和less

&#x1f388;归属专栏&#xff1a;从浅学到熟知Linux &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;每日一句&#xff1a;写完这篇我要去吃晚饭啦&#xff01;&#xff01; 文章前言&#xff1a;本文介绍cat、more和less指令三种查看文件的用法并给出示例和截图…

MUYUCMS v2.1:一款开源、轻量级的内容管理系统

MuYuCMS&#xff1a;一款基于Thinkphp开发的轻量级开源内容管理系统&#xff0c;为企业、个人站长提供快速建站解决方案。它具有以下的环境要求&#xff1a; 支持系统&#xff1a;Windows/Linux/Mac WEB服务器&#xff1a;Apache/Nginx/ISS PHP版本&#xff1a;php > 5.6 (…