【C++模块实现】| 【03】文件管理模块

发布于:2022-07-25 ⋅ 阅读:(568) ⋅ 点赞:(0)

文章目录

该模块是从sylar服务器框架中学习的,以下将会对其进行总结以加深对该框架的理解;

========》视频地址《========

参考内容

========》Linux系统编程 | 【02】文件I/O操作常用函数介绍《========
在这里插入图片描述

========》【C++】| 如何更好的利用do……while(0)《========
在这里插入图片描述

实现

/** 文件管理类 */
class FSUtil {
public:
    /**
     * @brief: 获取文件夹下的所有文件
     * @param files: 装载文件夹下的所有文件
     * @param path: 文件夹路径
     * @param subfix: 检索文件后缀
     * */
    static void ListAllFile(std::vector<std::string>& files
                            , const std::string& path
                            , const std::string& subfix);
    /**
     * @brief: 创建文件夹
     * @param dirname: 文件名
     * */
    static bool Mkdir(const std::string& dirname);
    /**
     * @brief: 判断该进程是否运行
     * */
    static bool IsRunningPidfile(const std::string& pidfile);
    /**
     * @brief: 删除文件
     * */
    static bool Rm(const std::string& path);
    /**
     * @brief: 移动文件
     * */
    static bool Mv(const std::string& from, const std::string& to);
    /**
     * @brief: 真正的文件路径
     * */
    static bool Realpath(const std::string& path,std::string& rpath);
    /**
     * @brief: 创建软连接
     * */
    static bool Symlink(const std::string& frm, const std::string& to);
    /**
     * @brief: 删除软连接
     * */
    static bool Unlink(const std::string& filename, bool exist= false);
    static std::string Dirname(const std::string& filename);
    static std::string Basename(const std::string& filename);
    static bool OpenForRead(std::ifstream& ifs, const std::string& filename
                            , std::ios_base::openmode mode);
    static bool OpenForWrite(std::ofstream& ofs, const std::string& filename
                            , std::ios_base::openmode mode);
};
/**
 * @brief: 获取文件夹下的所有文件
 * @param files: 装载文件夹下的所有文件
 * @param path: 文件夹路径
 * @param subfix: 检索文件后缀
 * */
void FSUtil::ListAllFile(std::vector<std::string>& files
                            , const std::string& path
                            , const std::string& subfix) {
    /** 判断该文件夹是否存在 */
    if(access(path.c_str(), 0) != 0)
        return;
    /** 打开文件夹 */
    DIR* dir = opendir(path.c_str());
    if(dir == nullptr)
        return;

    struct dirent* dp = nullptr;
    /* 循环读取文件夹下的文件名 */
    while ((dp = readdir(dir)) != nullptr) {
        /* 若该文件为文件夹 */
        if(dp->d_type == DT_DIR) {
            if(!strcmp(dp->d_name, "..")
                || !strcmp(dp->d_name, "."))
                continue;       // 若该文件为该两者,则直接跳过
            ListAllFile(files, path + "/" + dp->d_name, subfix);    // 递归执行
        /* 若为常规文件 */
        }else if(dp->d_type == DT_REG) {
            std::string filename(dp->d_name);
            if(subfix.empty()) {    // 若没有指定文件后缀
                files.push_back(path + "/" + filename);
            }else {
                /* 判断文件后缀是否满足 */
                if(filename.size() < subfix.size()) {
                    continue;
                }
                if(filename.substr(filename.length() - subfix.size()) == subfix) {
                    files.push_back(path + "/" + filename);
                }
            }
        }
    }
    closedir(dir);
}

/** 获取文件信息 */
static int __lstat(const char* file, struct stat* st = nullptr) {
    struct stat lst;
    int ret = lstat(file, &lst);
    if(st) {
        *st = lst;
    }

    return ret;
}

/** 创建文件夹 */
static int __mkdir(const char* dirname) {
    /* 判断该文件夹是否存在 */
    if(access(dirname, F_OK) == 0) {
        return 0;
    }
    return mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}

/** 创建文件夹 */
bool FSUtil::Mkdir(const std::string& dirname) {
    /* 检测文件夹是否存在 */
    if(__lstat(dirname.c_str()) == 0) {
        return true;
    }
    char* path = strdup(dirname.c_str());   // 获取一个新串副本
    char* ptr = strchr(path + 1, '/');  // 获取第一个出现/字符的位置
    /* 对文件路径进行切割,若出现多级目录,则创建多级目录 */
    do {
        for(; ptr; *ptr = '/', ptr = strchr(ptr + 1, '/')) {
            *ptr = '\0';
            if(__mkdir(path) != 0) {    // 创建文件夹
                break;
            }
        }
        if(ptr != nullptr) {
            break;
        }else if(__mkdir(path) != 0) {
            break;
        }
        free(path);
        return true;
    } while (0);
    free(path);

    return false;
}

bool FSUtil::IsRunningPidfile(const std::string& pidfile) {
    if(__lstat(pidfile.c_str()) != 0) {
        return false;
    }
    std::ifstream ifs(pidfile);
    std::string line;
    if(!ifs || !std::getline(ifs, line)) {
        return false;
    }
    if(line.empty()) {
        return false;
    }
    pid_t pid = atoi(line.c_str());
    if(pid <= 1) {
        return false;
    }
    if(kill(pid, 0)) {
        return false;
    }

    return true;
}

/**
 * @brief: 创建软连接
 * */
bool FSUtil::Symlink(const std::string& frm, const std::string& to) {
    if(!Rm(to)) {
        return false;
    }
    return ::symlink(frm.c_str(), to.c_str());
}

/**
 * @brief: 删除软连接
 * */
bool FSUtil::Unlink(const std::string& filename, bool exist) {
    if(!exist && __lstat(filename.c_str())) {
        return true;
    }
    return ::unlink(filename.c_str()) == 0;
}

/**
 * @brief: 删除文件
 * */
bool FSUtil::Rm(const std::string& path) {
    struct stat st;
    if(lstat(path.c_str(), &st)) {
        return true;
    }
    if(!(st.st_mode & S_IFDIR)) {
        return Unlink(path);
    }

    DIR* dir = opendir(path.c_str());
    if(!dir) {
        return false;
    }

    bool ret = true;
    struct dirent* dp = nullptr;
    while((dp = readdir(dir))) {
        if(!strcmp(dp->d_name, ".")
           || !strcmp(dp->d_name, "..")) {
            continue;
        }
        std::string dirname = path + "/" + dp->d_name;
        ret = Rm(dirname);
    }
    closedir(dir);
    if(::rmdir(path.c_str())) {
        ret = false;
    }
    return ret;
}

/** 移动文件 */
bool FSUtil::Mv(const std::string& from, const std::string& to) {
    if(!Rm(to)) {
        return false;
    }
    return rename(from.c_str(), to.c_str()) == 0;
}

/** 获取真实路径 */
bool FSUtil::Realpath(const std::string& path, std::string& rpath) {
    if(__lstat(path.c_str())) {
        return false;
    }
    char* ptr = ::realpath(path.c_str(), nullptr);
    if(nullptr == ptr) {
        return false;
    }
    std::string(ptr).swap(rpath);
    free(ptr);

    return true;
}


bool FSUtil::OpenForRead(std::ifstream& ifs, const std::string& filename
                        , std::ios_base::openmode mode) {
    ifs.open(filename.c_str(), mode);

    return ifs.is_open();
}

bool FSUtil::OpenForWrite(std::ofstream& ofs, const std::string& filename
        , std::ios_base::openmode mode) {
    ofs.open(filename.c_str(), mode);
    if(!ofs.is_open()) {
        std::string dir = Dirname(filename);
        Mkdir(dir);
        ofs.open(filename.c_str(), mode);
    }
    return ofs.is_open();
}

/** 返回文件名 */
std::string FSUtil::Dirname(const std::string& filename) {
    if(filename.empty()) {
        return ".";
    }
    auto pos = filename.rfind('/');
    if(pos == 0) {
        return "/";
    }else if(pos == std::string::npos) {
        return ".";
    }else {
        return filename.substr(0, pos);
    }
}

/** 返回文件名称 */
std::string FSUtil::Basename(const std::string& filename) {
    if(filename.empty()) {
        return filename;
    }
    auto pos = filename.rfind('/');
    if(pos == std::string::npos) {
        return filename;
    }else {
        return filename.substr(pos + 1);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到