C++文件系统操作2 - 跨平台实现文件夹的创建和删除
1. 关键词 C++ 文件系统操作 创建文件夹 创建多级目录文件夹 删除文件夹 删除文件夹下的所有文件和子目录 跨平台
2. fileutil.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #pragma once #include <string> #include <cstdio> #include <cstdint> #include "filetype.h" #include "filepath.h" namespace cutl{ class file_guard { public : explicit file_guard (FILE *file) ; ~file_guard (); FILE *getfd () const ; private : FILE *file_; }; bool createdir (const filepath &path, bool recursive = false ) ; bool removedir (const filepath &path, bool recursive = false ) ; }
3. fileutil.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 #include <cstdio> #include <map> #include <iostream> #include <cstring> #include <sys/stat.h> #include "fileutil.h" #include "inner/logger.h" #include "inner/filesystem.h" #include "strutil.h" namespace cutl{ file_guard::file_guard (FILE *file) : file_ (file) { } file_guard::~file_guard () { if (file_) { int ret = fclose (file_); if (ret != 0 ) { CUTL_ERROR ("fail to close file, ret" + std::to_string (ret)); } file_ = nullptr ; } } FILE *file_guard::getfd () const { return file_; } bool createdir (const filepath &path, bool recursive) { if (recursive) { constexpr int buf_size = MAX_PATH_LEN; char buffer[buf_size] = {0 }; int ret = snprintf (buffer, buf_size, "%s" , path.str ().c_str ()); if (ret < 0 || ret >= buf_size) { CUTL_ERROR ("invalid path: " + path.str ()); return false ; } int len = strlen (buffer); if (buffer[len - 1 ] != filepath::separator ()) { buffer[len++] = filepath::separator (); } int32_t idx = (buffer[0 ] == filepath::separator ()) ? 1 : 0 ; for (; idx < len; ++idx) { if (buffer[idx] != filepath::separator ()) { continue ; } buffer[idx] = '\0' ; filepath temp_path (buffer) ; if (!temp_path.exists ()) { if (!create_dir (temp_path.str ())) { CUTL_ERROR ("createdir error. dir:" + temp_path.str ()); return false ; } } buffer[idx] = filepath::separator (); } return true ; } else { auto dirPath = path.dirname (); if (dirPath.empty ()) { CUTL_ERROR ("invalid path: " + path.str ()); return false ; } if (!cutl::path (dirPath).exists ()) { CUTL_ERROR ("directory does not exist: " + dirPath); return false ; } return create_dir (path.str ()); } } bool removedir (const filepath &path, bool recursive) { if (!path.exists ()) { CUTL_ERROR ("directory does not exist: " + path.str ()); return false ; } if (recursive) { return remove_dir_recursive (path.str ()); } else { return remove_dir (path.str ()); } }
4. filesystem_win.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <vector> #include <string> #pragma once namespace cutl{ bool create_dir (const std::string &dir_path) ; bool remove_dir (const std::string &dir_path) ; bool remove_dir_recursive (const std::string &dir_path) ; }
5. filesystem_win.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 #if defined(_WIN32) || defined(__WIN32__) #include <io.h> #include <direct.h> #include <Windows.h> #include <stdlib.h> #include "strutil.h" #include "filesystem.h" #include "logger.h" namespace cutl{ bool create_dir (const std::string &dir_path) { if (_mkdir(dir_path.c_str ()) != 0 ) { CUTL_ERROR ("mkdir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } return true ; } bool remove_dir (const std::string &dir_path) { if (_rmdir(dir_path.c_str ()) != 0 ) { CUTL_ERROR ("rmdir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } return true ; } bool remove_dir_recursive (const std::string &dir_path) { auto findpath = dir_path + win_separator + "*.*" ; WIN32_FIND_DATAA data = {0 }; HANDLE hFind = FindFirstFileA (findpath.c_str (), &data); bool unicode = true ; if (hFind == INVALID_HANDLE_VALUE || hFind == NULL ) { CUTL_ERROR ("FindFirstFileA failed for " + findpath + ", errCode: " + std::to_string (GetLastError ())); return false ; } do { auto dwAttrs = data.dwFileAttributes; auto filename = std::string (data.cFileName); if (is_special_dir (filename)) { continue ; } std::string filepath = dir_path + win_separator + filename; if ((dwAttrs & FILE_ATTRIBUTE_DIRECTORY)) { if (!remove_dir_recursive (filepath)) { FindClose (hFind); return false ; } } else { int ret = remove (filepath.c_str ()); if (ret != 0 ) { CUTL_ERROR ("remove " + filepath + " error, ret:" + std::to_string (ret)); return false ; } } } while (FindNextFileA (hFind, &data)); FindClose (hFind); if (_rmdir(dir_path.c_str ()) != 0 ) { CUTL_ERROR ("rmdir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } return true ; } } #endif
6. filesystem_unix.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 #if defined(_WIN32) || defined(__WIN32__) #else #include <unistd.h> #include <sys/stat.h> #include <dirent.h> #include <stack> #include <cstring> #include <utime.h> #include <stdlib.h> #include <sys/time.h> #include "filesystem.h" #include "inner/logger.h" namespace cutl{ bool create_dir (const std::string &dir_path) { if (mkdir (dir_path.c_str (), S_IRWXU | S_IRWXG | S_IRWXO | S_IWOTH) != 0 ) { CUTL_ERROR ("mkdir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } return true ; } bool remove_dir (const std::string &dir_path) { if (rmdir (dir_path.c_str ()) != 0 ) { CUTL_ERROR ("rmdir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } return true ; } bool remove_dir_recursive (const std::string &dir_path) { DIR *dir = opendir (dir_path.c_str ()); if (dir == NULL ) { CUTL_ERROR ("opendir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } struct dirent *file_info = NULL ; while ((file_info = readdir (dir)) != NULL ) { std::string filename (file_info->d_name) ; if (is_special_dir (filename)) { continue ; } struct stat file_stat; std::string filepath = dir_path + unix_separator + filename; int ret = lstat (filepath.c_str (), &file_stat); if (0 != ret) { CUTL_ERROR ("stat error. filepath:" + filepath + ", error:" + strerror (errno)); closedir (dir); return false ; } if (S_ISDIR (file_stat.st_mode)) { if (!remove_dir_recursive (filepath)) { closedir (dir); return false ; } } else { int ret = remove (filepath.c_str ()); if (ret != 0 ) { CUTL_ERROR ("remove " + filepath + " error, ret:" + std::to_string (ret)); closedir (dir); return false ; } } } closedir (dir); int ret = rmdir (dir_path.c_str ()); if (ret != 0 ) { CUTL_ERROR ("rmdir error. dir_path:" + dir_path + ", error:" + strerror (errno)); return false ; } return true ; } } #endif
7. 源码地址 更多详细代码,请查看本人写的C++ 通用工具库: common_util , 本项目已开源,代码简洁,且有详细的文档和Demo。