Linux(CentOS)/Windows-C++ 云备份项目(项目文件操作工具类设计,完成项目基本文件操作-读写-压缩-目录操作)

本文详细描述了一个C++项目中的文件操作工具类,包括文件属性获取、基于C++17的文件读写、支持断点续传、文件压缩与解压缩功能,以及文件夹操作和错误处理机制。
摘要由CSDN通过智能技术生成

1. 项目文件操作工具类设计

根据前面的分析,这个文件类的基本属性如下:

  1. 文件大小信息
  2. 文件最后修改时间
  3. 文件最后一次访问时间,方便文件的热点管理
  4. 文件名称,需要从http 请求行上的uri中获取
  5. 基础文件读写接口 写数据为SetContent,读数据GetContent
  6. 获取文件指定位置,指定长度的数据,使其支持断点续传
  7. 获取文件夹的所有文件名称
  8. 判断文件是否存在方法
  9. 创建目录方法,名称是获取的文件名称
  10. 文件压缩解压缩方法

错误日志函数log.hpp

// 项目错误日志打印
#pragma once
#include <iostream>
#include <stdio.h>
#include <string>
#include <time.h>
#define INFO 1
#define WARNING 2
#define ERROR 3
#define FATAL 4
#define LOG(level, message) Log(#level, message, __FILE__, __LINE__) // #将宏参数转化为字符串

// 时间戳转化为时间信息
static std::string convertTimeStamp2TimeStr(time_t timeStamp)
{
    struct tm *timeinfo = nullptr;
    char buffer[80];
    timeinfo = localtime(&timeStamp);
    strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
    // printf("%s\n", buffer);
    return std::string(buffer);
}

// 日志级别+日志信息+时间戳+错误文件名称+错误行数
// 日志级别 INFO,WARNING,ERROR,FATAL
void Log(std::string level, std::string msg, std::string file_name, int line)
{

    std::cout << "[" << level << "]"
              << "[" << convertTimeStamp2TimeStr(time(nullptr)) << "]"
              << "[" << msg << "]"
              << "[" << file_name << "]"
              << "[" << line << "]" << std::endl;
}

文件工具类目录操作方法补充:

c库函数scandir函数:这个函数比较复杂使用这个也可以,这里使用C++17Filesystem类中的方法
在这里插入图片描述
Filesystem library (since C++17)

在这里插入图片描述
在这里插入图片描述
注意使用这个库需要在编译时加上-lstdc++fs

项目文件操作工具类设计:

#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/stat.h>
#include "log.hpp"
#include "../bundle/bundle.h"
// #include <filesystem>
#include <experimental/filesystem>
namespace CloudBackups
{
    namespace fs = std::experimental::filesystem;
    class FileUtil
    {
    private:
        std::string _filepath; // 文件名称 uri格式
        struct stat st;        // 文件属性

    public:
        FileUtil(const std::string &filepath)
        {
            _filepath = filepath;
            if (stat(_filepath.c_str(), &st) < 0)
            {
                LOG(WARNING, "get file stat failed! maybe this file not exits");
            }
        }
        int64_t filesize() { return st.st_size; }         // 获取文件大小,失败返回-1
        time_t last_modify_time() { return st.st_mtime; } // 获取文件最后修改时间
        time_t last_visit_time() { return st.st_atime; }  // 获取文件最后访问时间
        std::string filename()                            // 文件名称
        {
            size_t pos = _filepath.find_last_of("/");
            if (pos == std::string::npos)
            {
                return _filepath;
            }
            return _filepath.substr(pos + 1);
        }
        bool getPoslen(std::string &body, size_t pos, size_t len) // 从文件中读取len个字节,从pos位置开始读取,读取内容放到body中,为了实现断点续传
        {
            size_t size = this->filesize(); // 文件大小
            if (pos >= size)
            {
                LOG(ERROR, "pos is out of range!");
                return false;
            }
            if (pos + len > size)
            {
                LOG(ERROR, "pos + len is out of range!");
                return false;
            }
            std::ifstream ifs;
            ifs.open(_filepath.c_str(), std::ios::binary);
            if (!ifs.is_open())
            {
                LOG(ERROR, "open file failed!");
                return false;
                
            }
            ifs.seekg(pos, std::ios::beg);
            body.resize(len);
            ifs.read(&body[0], len);
            if (!ifs.good())
            {
                // 上次读取出错
                LOG(ERROR, "read file failed!");
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }
        bool getContent(std::string &body) // 获取整体的文件数据
        {
            size_t size = this->filesize();
            return getPoslen(body, 0, size);
        }
        bool setContent(const std::string &body) // 设置文件内容
        {
            std::ofstream ofs;
            ofs.open(_filepath.c_str(), std::ios::binary);
            if (!ofs.is_open())
            {
                LOG(ERROR, "open file failed!");
                return false;
            }
            ofs.write(body.c_str(), body.size());
            if (!ofs.good())
            {
                // 上次写入出错
                LOG(ERROR, "write file failed!");
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }
        bool zip(const std::string &packname) // 文件压缩功能,传入压缩后名称
        {
            // 读取源文件所有内容
            std::string body;
            if (this->getContent(body) == false)
            {
                // 获取源文件数据失败
                LOG(ERROR, "get file content failed!");
                return false;
            }
            // 对数据进行压缩
            std::string packed = bundle::pack(bundle::LZIP, body);
            // 保存压缩后的数据
            FileUtil file(packname);
            if (file.setContent(packed) == false)
            { // 保存压缩后的数据失败
                LOG(ERROR, "save zip file content failed!");
                return false;
            }
            return true;
        }
        bool unzip(const std::string &filename) // 文件解压缩功能,传入解压缩文件名称
        {
            // 读取当前压缩的数据
            std::string body;
            if (this->getContent(body) == false)
            {
                // 获取源文件数据失败
                LOG(ERROR, "get zip file content failed!");
                return false;
            }
            // 对压缩的数据进行解压
            std::string unpacked = bundle::unpack(body);
            // 保存解压数据
            FileUtil file(filename);
            if (file.setContent(unpacked) == false)
            { // 保存解压数据失败
                LOG(ERROR, "save unzip file content failed!");
                return false;
            }
            return true;
        }
        bool isExit() { return fs::exists(_filepath); } // 判断文件是否存在
        bool mkdir()                                    // 创建文件夹
        {
            if (this->isExit())
            {
                return true;
            }
            return fs::create_directories(_filepath);
        }
        bool ls(std::vector<std::string> &files) // 扫描文件夹,并返回里面的文件
        {
            for (auto &pos : fs::directory_iterator(_filepath))
            {
                if (fs::is_directory(pos) == true)
                {
                    continue; // 目录不出来
                }
                files.push_back(fs::path(pos).relative_path().string()); // 获取文件的相对路径
            }
            return true;
        }
    };
}

在这里插入图片描述
在这里插入图片描述

根据上图可知,项目文件属性获取,文件读写,文件压缩与解压缩基本功能没有问题

代码位置:
Gitee地址
Gitee地址

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值