• Linux环境下用C++删除指定文件


    Linux环境下用C++删除指定文件

    ”Talk is cheap, show me the code!“

    #include <cstdio>
    #include <string>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <iostream>
    #include <vector>
    #include <dirent.h>
    #include <time.h>
    using namespace std;
    
    const long day = 86400;
    
    //获取文件的给更新时间
    long get_file_modify_time(string filepath)
    {
        struct stat filehand;
        FILE *fp;
        fp = fopen(filepath.c_str(), "r");
        int fileid = fileno(fp);
        fstat(fileid, &filehand);
        fclose(fp);
        return filehand.st_mtime;
    }
    //获取文件夹中的所有文件
    void get_files(const string dirname, vector<string> &filelist)
    {
        if(dirname.empty())
            return;
        struct stat s;
        stat(dirname.c_str(), &s);
        if(!S_ISDIR(s.st_mode))
            return;
        DIR *dirhand = opendir(dirname.c_str());
        if(NULL == dirhand){
            exit(EXIT_FAILURE);
        }
        dirent *fp = nullptr;
        while((fp = readdir(dirhand)) != nullptr){
            if(fp->d_name[0] != '.'){//十分重要的一行(?)
                string filename = dirname + "/" + string(fp->d_name);
                struct stat filemod;
                stat(filename.c_str(), &filemod);
                if(S_ISDIR(filemod.st_mode)){
                    get_files(filename, filelist);
                }
                else if(S_ISREG(filemod.st_mode)){
                    filelist.push_back(filename);
                }
            }
        }
        closedir(dirhand);
        return;
    }
    
    bool delete_file(string filepath)
    {
        return remove(filepath.c_str());
    }
    
    bool date_from_now(long now, long modify)
    {
        int dis = int((1.0 * (now - modify) / day + 0.5));
        return dis >= 9;//删除最近更新时间距今超过14天的文件
    }
    
    int main()
    {
        time_t now;
        time(&now);//获取当前系统时间
        string dir = "/file/cpp";//需要处理的文件夹
        vector<string> filelist;
        get_files(dir, filelist);//获取文件夹中的所有文件
        for(auto i : filelist){
            if(date_from_now(now, get_file_modify_time(i))){
                cout << i << endl;
                if(!delete_file(i)){
                    cout << "The file named : " << i << " has been deleted." << endl;
                }
                else{
                    cout << "Delete Failed!" << endl;
                }
            }
        }
        return 0;
    }
    

    如果没有详细学习过linux下编程,可能看不太懂这些代码,接下来详细分析:

    获取文件最后更新时间

    对应代码

    //获取文件的给更新时间
    long get_file_modify_time(string filepath)
    {
        struct stat filehand;
        FILE *fp;
        fp = fopen(filepath.c_str(), "r");
        int fileid = fileno(fp);
        fstat(fileid, &filehand);
        fclose(fp);
        return filehand.st_mtime;
    }
    

    代码中用到了stat数据结构和文件操作,学过c的同学应该对文件操作都比较熟悉。

    struct stat是一种保存文件信息的数据结构,使用这个结构体和一些相应的函数,需要包含

    <sys/types.h>和<sys/stat.h>

    对于一个文件我们可以用fstat函数来获取这个文件所对应的数据结构,fstat(int fid, struct stat *struct_stat)

    其中fid为文件的描述符,可以理解为文件的一个唯一编号,获取这个编号我们就要用到文件操作函数。

    首先用fopen()打开文件并获取文件指针,之后用fileno()获取文件的描述符。

    对于struct stat中的属性包括:

    struct stat {
            mode_t     st_mode;       //文件对应的模式,文件,目录等
            ino_t      st_ino;       //inode节点号
            dev_t      st_dev;        //设备号码
            dev_t      st_rdev;       //特殊设备号码
            nlink_t    st_nlink;      //文件的连接数
            uid_t      st_uid;        //文件所有者
            gid_t      st_gid;        //文件所有者对应的组
            off_t      st_size;       //普通文件,对应的文件字节数
            time_t     st_atime;      //文件最后被访问的时间
            time_t     st_mtime;      //文件内容最后被修改的时间
            time_t     st_ctime;      //文件状态改变时间
            blksize_t st_blksize;    //文件内容对应的块大小
            blkcnt_t   st_blocks;     //伟建内容对应的块数量
    };
    

    我们需要获取的是文件的最近更新时间,也就是st_mtime(注意:这个属性所表示的时间是距离1970年1月1日0点0分0秒[国际标准时间]的秒数)。

    获取所有的文件

    对应代码

    //获取文件夹中的所有文件
    void get_files(const string dirname, vector<string> &filelist)
    {
        if(dirname.empty())
            return;
        struct stat s;
        stat(dirname.c_str(), &s);
        if(!S_ISDIR(s.st_mode))
            return;
        DIR *dirhand = opendir(dirname.c_str());
        if(NULL == dirhand){
            exit(EXIT_FAILURE);
        }
        dirent *fp = nullptr;
        while((fp = readdir(dirhand)) != nullptr){
            if(fp->d_name[0] != '.'){//十分重要的一行
                string filename = dirname + "/" + string(fp->d_name);
                struct stat filemod;
                stat(filename.c_str(), &filemod);
                if(S_ISDIR(filemod.st_mode)){
                    get_files(filename, filelist);
                }
                else if(S_ISREG(filemod.st_mode)){
                    filelist.push_back(filename);
                }
            }
        }
        closedir(dirhand);
        return;
    }
    

    在这部分中我们要用到关于文件夹处理的一些函数和结构体,需要引入<dirent.h>头文件

    在这部分中,首先我们要为函数传入两个参数,需要处理的文件所在的文件夹,和一个文件列表(用来保存所有文件的信息,这里用vector实现)

    首先我们先将文件夹保存为struct stat变量,然后借助S_ISDIR()函数来判断这是否是一个文件夹,如果不是则退出,如果是,我们要使用DIR结构体来保存文件夹的信息。

    DIR可以定义一个文件夹结构体变量,其值由opendir(char *file_path)函数获得。

    之后用dirent变量可以遍历文件夹中的所有文件,包括文件夹在内。dirent变量的值由readdir(DIR *p)函数获得。

    dirent结构体中保存的属性有:

    struct dirent
    {
       long d_ino; /* inode number 索引节点号 */
       off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
       unsigned short d_reclen; /* length of this d_name 文件名长 */
       unsigned char d_type; /* the type of d_name 文件类型 */
       char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
    }
    

    这里我们需要用到d_name字符串来获取文件名并组成文件路径,需要注意的是:在一个文件夹中最开始的两个目录是”.“文件和".."文件,这个用vim打印文件树的时候可以看到,这两个分别代表当前目录和父目录,所以我们要在遍历时排除这两个文件,否则会产生无限递归,程序崩溃!!!

    除了S_ISDIR()函数我们还会用到S_ISREG()函数,是为了判断文件是否为普通文件。

    获取系统当前时间

        time_t now;
        time(&now);//获取当前系统时间
    

    这里用到time()函数,需要包含<time.h>库

    删除文件

    bool delete_file(string filepath)
    {
        return remove(filepath.c_str());
    }
    

    c++可以使用remove()函数执行文件的删除操作。


  • 相关阅读:
    移动web前端高效开发实践 读书笔记
    前端开发最佳实践-读书笔记
    frontend-Tips
    匿名函数的几种写法
    12个用得着的JQuery代码片段(转)
    tesseract-ocr 学习笔记(比网上的中文说明都详细)
    关于大数据的思考
    单片机实验的小记录~~PWM
    组建Redis集群遇到`GLIBC_2.14' not found和ps -ef 不显示用户名
    柔性数组(Redis源码学习)
  • 原文地址:https://www.cnblogs.com/LeafLove/p/12512844.html
Copyright © 2020-2023  润新知