该模块是从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)《========
实现
/** 文件管理类 */
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);
}
}