【百度云盘项目实践(2)】:文件实用类工具设计

                 197b70d6176541c0a5b6a2b9362613a9.png

                                                    

                    🎁个人主页 :离芩

                 🔍系列专栏:Linux实战

        🎉欢迎大家点赞👍评论📝收藏⭐文章 !!!

                                                           55a62c5debf843138b1cec01017941fd.gif

              bed2f6a8294b4c0db1fb1c26b62eba26.gif

 

hello !大家好呀! 欢迎大家来到我的Linux项目实战系列之《【百度云盘项目实践(2)】:文件实用类工具设计》,在这篇文章中,你将会学习到在云盘项目中,我们怎样去管理我们的文件,我会手绘UML图来帮助大家来理解,希望能让大家更能了解网络编程技术!!!

希望这篇文章能对你有所帮助,大家要是觉得我写的不错的话,那就点点免费的小爱心吧!(注:这章对于高性能服务器的实现非常重要哟!!!)

03d6d5d7168e4ccb946ff0532d6eb8b9.gif           

目录

 🔍一.文件管理类设计思想

🔍二.文件信息获取函数设计

 🎉  2.1  int64_t FileSize();

🎉 2.2 time_t LastTime()和string FileName();

🎉 2.3 string FileName() ;

🔍三.文件内容获取与修改函数设计

 🎉 3.1  bool GetPosLen(std:: string *body , size_t pos ,size_t len) 

🎉3.2 bool SetContent(const std::string &body) 

🔍四.压缩与解压缩

🔍五.目录功能函数设计

🎉1. CreateDirectory函数

🎉2. ScanDirectory函数


 

 

 

 一.文件管理类设计思想

        对与文件的管理,我们需要设计一个实用类来进行文件管理,其中包括文件信息的获取,修改,以及文件的压缩与解压缩,文件目录的创建,资源的访问,以及json数据序列号与反序列化的接口包装。

        因此我们依据上面要求,设计出这样一个类:

3e70850301404440871901c6e0d6ac93.jpeg

 这个文件管理类中的数据成员只有一个,也就是文件名,我们根据这个类中的文件名对文件进行管理,包括类的实例化,文件大小的获取,文件修改时间与最新访问时间,文件名的获取,获取指定大小区间的文件内容,设置文件内容,文件的压缩与解压缩,目录的创建与浏览。

         这些函数的实现都使用了许多外接库与接口,接下来我就给大家详细解读这些函数的实现与运用吧!!!

 

二.文件信息获取函数设计

        对于文件信息的获取,我们需要实现文件大小的获取,文件修改时间与最新访问时间,文件名的获取。

   2.1  int64_t FileSize();

         这是文件大小的获取函数:

int64_t FileSize(){
                    struct stat st;//获取文件信息接口
                    if(stat(_filename.c_str() , &st)< 0){
                        return -1;
                        std::cout<< "Get file_size failed\n";
                        return -1;
                    }
                    return st.st_size;//返回文件大小
                
            }//获取文件大小

我们实用了stat函数,可以直接获取整个文件的信息,需要了解这个函数的可以去看我之前的博客。 

 2.2 time_t LastTime()和string FileName();

         这是文件最后的修改时间和访问时间的获取,与上面函数一样,使用stat函数即可:

time_t LastTime(){
                    struct stat st;//获取文件信息接口
                    if(stat(_filename.c_str() , &st)< 0){
                        return -1;
                        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){
                        return -1;
                        std::cout<< "Get file_size failed\n";
                        return -1;
                    }
                    return st.st_atime;
                
            }//文件最后一次访问时间

  2.3 string FileName() ;

        这个函数用于获取在给定一个路径下,获取我们目标文件名称,意思是只要文件名,前面的路径都给去除,这个函数虽然简单但是却十分重要的。

std::string FileName(){
                // ./abc/test.tst
                size_t pos = _filename.find_last_of("/");//找到路径的最后一个斜杠
                if(pos == std::string::npos){//本身就是文件名
                    return _filename;
                }
                return _filename.substr(pos+1);
            }//文件名称获取

 

三.文件内容获取与修改函数设计

  3.1  bool GetPosLen(std:: string *body , size_t pos ,size_t len) 

bool GetPosLen(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<< "open file failed\n";
                    return false ;
                }
                size_t fsize = this->FileSize();//获取当前文件大小
                if(pos + len > fsize){//超出文件大小 
                    std::cout<<" get file len is erron\n";
                    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\n";
                    ifs.close();
                    return false;
                }
                ifs.close();
                return true;
            }

 这个函数`GetPosLen`的目的是从一个文件中读取指定位置和长度的数据。
1. 函数参数
   - `std::string *body`: 一个指向`std::string`的指针,用于存储从文件中读取的数据。
   - `size_t pos`: 指定从文件开始的读取位置。
   - `size_t len`: 指定要读取的数据长度。


2. 文件操作
   - 使用`std::ifstream`类打开一个文件(文件名是类的一个成员变量`_filename`),以二进制模式打开。
   - 检查文件是否成功打开。如果打开失败,打印错误信息并返回`false`。


3. 检查读取长度
   - 通过调用`FileSize()`函数(这也是类的一个成员函数)获取文件大小。
   - 检查请求的读取位置加上长度是否超出文件大小。如果超出,打印错误信息并返回`false`。


4. 读取数据
   - 使用`seekg()`函数将文件读指针定位到指定的位置`pos`。
   - 调整`body`指向的`std::string`的大小,使其等于`len`。
   - 使用`read()`函数从文件中读取`len`长度的数据到`body`指向的`std::string`中。
   - 检查读取操作是否成功。如果失败,打印错误信息,关闭文件,并返回`false`。


5. 结束操作
   - 关闭文件。
   - 如果所有操作都成功,返回`true`。
这个函数主要用于从大型文件中安全地读取特定部分的数据,适用于需要处理大文件或需要从特定位置读取数据的应用场景。
 

 

3.2 bool SetContent(const std::string &body) 

        这是向文件内写入数据,代码与查看相似,这里就不多解释了,有不懂的可以直接百度

bool GetContent(std:: string *body){//获取文件全部内容
                size_t fsize = this->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 failed.\n";
                    return false;
                }
                ofs.write(&body[0] , body.size());//写入数据
                if(ofs.good() == false){
                    std::cout<<"write file content failed!\n";
                    ofs.close();
                    return false;
                }
                ofs.close();
                return true;
            }

四.压缩与解压缩

         对于文件的压缩与解压缩,这是云盘处理文件的一个很重要的功能,对于一些大型文件与非热点文件,我们服务器一般都会备份压缩。

         压缩与解压缩接口实现:

bool Compress(const std::string &packname){//压缩功能
                //1.读取源文件数据
                std::string body;
                if(this->GetContent(&body) == false){
                    std::cout<< "compress get file content failen!\n";
                    return false;
                }
                //2.对文件进行压缩
                std::string packed = bundle::pack(bundle::LZIP, body);
                //将压缩的数据存入数据包文件
                FileUtil fu(packname);
                if(fu.SetContent(packed) == false){
                    std::cout<<" compress write packed failed!\n";
                    return false;
                }
                return true;
            }
            bool uncompress(const std::string &filenmae){
                //1.将当前压缩包数据读取
                std::string body;
                if(this->GetContent(&body) == false){
                    std::cout<<"uncompress write packed data failed!\n";
                    return false;
                }
                //将压缩数据解压缩
                std::string unpacked = bundle::unpack(body);
                //将解压缩数据写入到新文件
                FileUtil fu(filenmae);
                if(fu.SetContent(unpacked) == false){
                     std::cout<<" uncompress write packed failed!\n";
                    return false;
                }
                return true;
            }

 这两个函数`Compress`和`uncompress`分别用于文件的压缩和解压缩。


  1. `Compress`函数
这个函数的目的是将当前文件压缩,并保存到指定的压缩包文件中。
- **读取源文件数据**:
  - 调用`GetContent`函数(假设这是类的一个成员函数)来读取整个文件的内容到`body`字符串中。如果读取失败,打印错误信息并返回`false`。
- **文件压缩**:
  - 使用`bundle::pack(bundle::LZIP, body)`函数(假设这是定义在某个命名空间`bundle`中的一个函数,用于压缩数据)对读取到的数据进行压缩。这里使用的是LZIP压缩算法。
- **保存压缩数据**:
  - 使用`FileUtil`类(假设这是一个用于文件操作的辅助类)的实例`fu`,调用`SetContent`方法将压缩后的数据`packed`写入到指定的压缩包文件`packname`中。如果写入失败,打印错误信息并返回`false`。
- **返回结果**:
  - 如果所有操作都成功,返回`true`

2. `uncompress`函数
这个函数的目的是将压缩包中的文件解压缩,并保存到指定的文件中。
- **读取压缩包数据**:
  - 调用`GetContent`函数读取压缩包文件的内容到`body`字符串中。如果读取失败,打印错误信息并返回`false`。
- **文件解压缩**:
  - 使用`bundle::unpack(body)`函数(假设这是定义在`bundle`命名空间中的一个函数,用于解压缩数据)对读取到的数据进行解压缩。
- **保存解压缩数据**:
  - 使用`FileUtil`类的实例`fu`,调用`SetContent`方法将解压缩后的数据`unpacked`写入到指定的文件`filenmae`中。如果写入失败,打印错误信息并返回`false`。
- **返回结果**:
  - 如果所有操作都成功,返回`true`。
这两个函数共同构成了一个简单的文件压缩和解压缩工具,可以用于处理文件的压缩与解压操作。

   具体内容可以参考我上一篇博客:【百度云盘项目实践(1)】:探索JSON与Bundle库的结合应用-CSDN博客

 

五.目录功能函数设计

         对于云盘文件管理,我们需要用户在下载或者查看文件内容时,给予用户方便的目录进行查看和下载,接口函数实现如下:

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;
            }
    };

1. CreateDirectory函数

这个函数的目的是创建一个目录。

  • 检查目录是否存在:

    • 调用Exists函数(假设这是类的一个成员函数)来检查指定的目录(_filename,这是类的一个成员变量)是否存在。如果目录已经存在,直接返回true
  • 创建目录:

    • 如果目录不存在,使用std::filesystem::create_directories函数(这是C++17中引入的文件系统库中的函数)来创建目录。这个函数会创建所有必要的中间目录,所以即使多层目录不存在,也会被创建。
    • 函数返回创建操作的结果(true表示成功,false表示失败)。

2. ScanDirectory函数

这个函数的目的是列出指定目录下的所有文件,但不包括子目录。

  • 遍历目录:

    • 使用std::filesystem::directory_iterator来遍历指定目录(_filename)中的所有条目。
  • 检查条目类型:

    • 对于每个条目,使用std::filesystem::is_directory函数检查它是否是一个目录。如果是目录,则跳过,继续下一次循环。
  • 获取文件名:

    • 对于不是目录的条目,使用std::filesystem::path来获取其路径,并调用relative_path()方法来获取相对于当前目录的路径。
    • 将文件名(相对路径)转换为字符串,并添加到arry向量中。
  • 返回结果:

    • 函数总是返回true,不论操作是否成功。这可能是一个设计上的考虑,或者可能是一个错误,因为通常情况下,如果目录不存在或者无法遍历,应该返回false

这两个函数可以用于文件系统操作,如创建目录和扫描目录内容,常用于文件管理和资源组织等场景。

     好啦!到这里这篇文章就结束啦,关于实例代码中我写了很多注释,如果大家还有不懂得,可以评论区或者私信我都可以哦4d7d9707063b4d9c90ac2bca034b5705.png!! 感谢大家的阅读,我还会持续创造网络编程相

关内容的,记得点点小爱心和关注哟!

2cd0d6ee4ef84605933ed7c04d71cfef.jpeg   

 

  • 84
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 71
    评论
评论 71
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值