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

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

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

索引

【C++模块实现】| 【01】日志系统实现
【C++模块实现】| 【02】日志系统优化
【C++模块实现】| 【03】文件管理模块
【C++模块实现】| 【04】配置模块
【C++模块实现】| 【05】日志模块增加配置模块的功能
【C++模块实现】| 【06】日志模块添加循环覆盖写文件功能
【C++模块实现】| 【07】对于互斥、自旋锁、条件变量、信号量简介及封装
【C++模块实现】| 【08】循环覆盖写内存缓冲区(日志中多线程记录)
【C++模块实现】| 【09】线程模块及线程池的实现
【C++模块实现】| 【10】定时器的实现
【C++模块实现】| 【11】封装Ipv4、Ipv6、unix网络地址

参考内容

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

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

========》ifstream《=========
在这里插入图片描述

实现

/** 文件管理类 */
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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++ 中,模块定义文件(Module Definition File)通常使用 .def 扩展名。它是一种文本文件,用于定义模块的导出函数、变量以及其他相关信息。模块定义文件可以在编译和链接过程中指定模块的导出和导入行为。 下面是使用模块定义文件的一般步骤: 1. 创建一个新的文本文件,并将其扩展名设置为 .def,例如 `mymodule.def`。 2. 在 .def 文件中,使用关键字 `LIBRARY` 来指定模块的名称,例如 `LIBRARY mymodule`。 3. 使用关键字 `EXPORTS` 来列出需要导出的函数和变量。每个导出项应该占据一行,并且可以使用通配符来指定一组相关项。例如: ``` EXPORTS MyFunction1 MyFunction2 MyVariable SomeModuleFunction* ``` 这将导出名为 "MyFunction1"、"MyFunction2" 和 "MyVariable" 的函数和变量,以及以 "SomeModuleFunction" 开头的所有函数。 4. 保存并关闭 .def 文件。 在使用模块定义文件时,你需要在编译和链接过程中指定该文件。具体方法取决于你使用的编译器和构建工具。以下是一些常用的方法: - 在命令行中使用编译器时,可以将 .def 文件作为参数传递给编译器。例如: ``` g++ mymodule.cpp mymodule.def -o mymodule.exe ``` - 使用集成开发环境(IDE)时,可以在项目设置或构建配置中指定 .def 文件。 使用模块定义文件可以控制模块的导出行为,例如在动态链接库中导出函数和变量。这对于实现模块的封装和公共接口非常有用。请注意,模块定义文件的具体语法和支持程度可能因编译器和操作系统而有所不同,建议查阅相关文档以了解更多详细信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jxiepc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值