转载地址:https://github.com/offscum/tinyToolkit/blob/dev/project/tinyToolkit/utilities/filesystem.cpp
/** * * 作者: hm * * 说明: 文件处理 * */ #include "filesystem.h" namespace tinyToolkit { /** * * 文件是否存在 * * @param path 文件路径 * * @return 文件是否存在 * */ bool Filesystem::Exists(const std::string & path) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS return _access(path.c_str(), S_OK) == 0; #else return access(path.c_str(), F_OK) == 0; #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 删除目录 * * @param path 文件路径 * * @return 文件是否删除 * */ bool Filesystem::Remove(const std::string & path) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS if (IsDirectory(path)) { std::string dir{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { dir = path + "*.*"; } else { dir = path + TINY_TOOLKIT_FOLDER_SEP + "*.*"; } WIN32_FIND_DATA finder{ }; HANDLE hFind = FindFirstFile(dir.c_str(), &finder); if (hFind == INVALID_HANDLE_VALUE) { throw std::runtime_error("No such file or directory : [" + path + "]"); } do { if (strcmp(finder.cFileName, ".") == 0 || strcmp(finder.cFileName, "..") == 0) { continue; } std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + finder.cFileName; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + finder.cFileName; } if (finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (!Remove(value)) { return false; } } else { if (DeleteFile(value.c_str()) == FALSE) { return false; } } } while (FindNextFile(hFind, &finder)); if (RemoveDirectory(path.c_str()) == FALSE) { return false; } return true; } else { return DeleteFile(path.c_str()) == TRUE; } #else if (IsDirectory(path)) { DIR * dir = opendir(path.c_str()); if (dir == nullptr) { throw std::runtime_error("No such file or directory : [" + path + "]"); } struct dirent * dirEvent = readdir(dir); while (dirEvent) { if (dirEvent->d_name[0] != '.') { std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + dirEvent->d_name; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + dirEvent->d_name; } if (IsDirectory(value)) { if (!Remove(value)) { closedir(dir); return false; } } else { if (std::remove(value.c_str()) == -1) { closedir(dir); return false; } } } dirEvent = readdir(dir); } if (std::remove(path.c_str()) == -1) { closedir(dir); return false; } closedir(dir); return true; } else { return std::remove(path.c_str()) == 0; } #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 更改文件名称 * * @param src 待更改文件路径 * @param dst 被更改文件路径 * * @return 文件是否更改 * */ bool Filesystem::Rename(const std::string & src, const std::string & dst) { if (std::rename(src.c_str(), dst.c_str()) == 0) { return true; } else { throw std::runtime_error("Failed Rename [" + src + "] to [" + dst + "]"); } } /** * * 是否为目录 * * @param path 待检测文件路径 * * @return 是否为目录 * */ bool Filesystem::IsDirectory(const std::string & path) { if (Exists(path)) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS return GetFileAttributesA(path.c_str()) & FILE_ATTRIBUTE_DIRECTORY; #else struct stat status{ }; if (::stat(path.c_str(), &status) == -1) { throw std::runtime_error("Failed stat : [" + path + "]"); } return S_ISDIR(status.st_mode); #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } else { return false; } } /** * * 文件大小 * * @param path 文件路径 * * @return 文件大小 * */ std::size_t Filesystem::Size(const std::string & path) { std::ifstream ifs(path, std::ifstream::ate | std::ifstream::binary); if (ifs.is_open()) { std::size_t size = static_cast<std::size_t>(ifs.tellg()); ifs.close(); return size; } else { throw std::runtime_error("Failed open file : [" + path + "]"); } } /** * * 文件内容 * * @param path 待读取文件路径 * * @return 文件内容 * */ std::string Filesystem::Content(const std::string & path) { std::ifstream ifs(path, std::ios::binary); if (ifs.is_open()) { std::string str((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())); ifs.close(); return str; } else { throw std::runtime_error("Failed open file : [" + path + "]"); } } /** * * 读取文件内容 * * @param path 待读取文件路径 * @param container 结果容器 * @param keepEmpty 是否保留空行 * * @return 读取行数 * */ std::size_t Filesystem::ReadFile(const std::string & path, std::vector<std::string> & container, bool keepEmpty) { std::ifstream ifs(path, std::ios::binary); if (ifs.is_open()) { std::string str{ }; while (!ifs.eof()) { std::getline(ifs, str); if (!ifs.good()) { break; } if (keepEmpty || !str.empty()) { container.push_back(str); } } ifs.close(); } else { throw std::runtime_error("Failed open file : [" + path + "]"); } return container.size(); } /** * * 读取文件内容 * * @param path 待读取文件路径 * @param keepEmpty 是否保留空行 * * @return 结果容器 * */ std::vector<std::string> Filesystem::ReadFile(const std::string & path, bool keepEmpty) { std::vector<std::string> container; ReadFile(path, container, keepEmpty); return container; } /** * 创建文件 * * @param path 待创建文件路径 * * @return 创建结果 * */ bool Filesystem::CreateFile(const std::string & path) { std::ofstream ofs(path, std::ios::binary); if (ofs.is_open()) { ofs.close(); return true; } return false; } /** * * 创建文件夹 * * @param path 待创建文件路径 * * @return 创建结果 * */ bool Filesystem::CreateDirectory(const std::string & path) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS if (_mkdir(path.c_str()) == -1) { if (!Exists(path)) { throw std::runtime_error("Failed create directory : [" + path + "]"); } } return true; #else if (mkdir(path.c_str(), 0777) == -1) { if (!Exists(path)) { throw std::runtime_error("Failed create directory : [" + path + "]"); } } return true; #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 创建层级目录 * * @param path 待创建目录路径 * * @return 创建结果 * */ bool Filesystem::CreateDirectories(const std::string & path) { std::size_t size = path.size(); for (std::size_t i = 0; i < size; ++i) { if (i == (size - 1)) { if (!CreateDirectory(path)) { return false; } } else if (path[i] == TINY_TOOLKIT_FOLDER_SEP[0]) { if (i == 0) { continue; } if (!CreateDirectory(path.substr(0, i))) { return false; } } } return true; } /** * * 当前目录 * * @return 当前目录 * */ std::string Filesystem::CurrentDirectory() { char directory[TINY_TOOLKIT_PATH_MAX + 1] = { 0 }; #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS return _getcwd(directory, TINY_TOOLKIT_PATH_MAX) ? directory : TINY_TOOLKIT_FOLDER_EOL; #else return getcwd(directory, TINY_TOOLKIT_PATH_MAX) ? directory : TINY_TOOLKIT_FOLDER_EOL; #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 文件名 * * @param path 待处理文件路径 * * @return 文件名 * */ std::string Filesystem::Name(const std::string & path) { std::size_t pos = path.rfind(TINY_TOOLKIT_FOLDER_SEP[0]); return pos == std::string::npos ? path : path.substr(pos + 1); } /** * * 文件前缀 * * @param path 待处理文件路径 * * @return 文件前缀 * */ std::string Filesystem::Steam(const std::string & path) { std::size_t srcPos = path.rfind(TINY_TOOLKIT_FOLDER_SEP[0]); std::size_t dstPos = path.rfind('.'); if (srcPos == std::string::npos) { return dstPos == std::string::npos ? path : path.substr(0, dstPos); } else { return (dstPos == std::string::npos || dstPos < srcPos) ? path.substr(srcPos + 1) : path.substr(srcPos + 1, dstPos - srcPos - 1); } } /** * * 绝对路径 * * @param path 待处理路径 * * @return 绝对路径 * */ std::string Filesystem::Canonical(const std::string & path) { char directory[TINY_TOOLKIT_PATH_MAX + 1] = { 0 }; #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS return _fullpath(directory, path.c_str(), TINY_TOOLKIT_PATH_MAX) ? directory : TINY_TOOLKIT_FOLDER_EOL; #else return realpath(path.c_str(), directory) ? directory : TINY_TOOLKIT_FOLDER_EOL; #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 文件扩展名 * * @param path 待处理文件路径 * * @return 文件扩展名 * */ std::string Filesystem::Extension(const std::string & path) { std::size_t srcPos = path.rfind(TINY_TOOLKIT_FOLDER_SEP[0]); std::size_t dstPos = path.rfind('.'); if (srcPos == std::string::npos) { return dstPos == std::string::npos ? "" : path.substr(dstPos); } else { return (dstPos == std::string::npos || dstPos < srcPos) ? "" : path.substr(dstPos); } } /** * * 父级路径 * * @param path 待处理路径 * * @return 父级路径 * */ std::string Filesystem::ParentDirectory(const std::string & path) { std::size_t pos = path.rfind(TINY_TOOLKIT_FOLDER_SEP[0]); if (pos == std::string::npos) { return CurrentDirectory(); } else { return path.substr(0, pos); } } /** * * 遍历文件 * * @param path 待遍历根目录路径 * @param container 文件结果容器 * @param subdirectory 是否遍历子目录 * */ void Filesystem::TraverseFile(const std::string & path, std::vector<std::string> & container, bool subdirectory) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS std::string dir{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { dir = path + "*.*"; } else { dir = path + TINY_TOOLKIT_FOLDER_SEP + "*.*"; } WIN32_FIND_DATA finder{ }; HANDLE hFind = FindFirstFile(dir.c_str(), &finder); if (hFind == INVALID_HANDLE_VALUE) { throw std::runtime_error("No such file or directory : [" + path + "]"); } do { if (strcmp(finder.cFileName, ".") == 0 || strcmp(finder.cFileName, "..") == 0) { continue; } std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + finder.cFileName; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + finder.cFileName; } if (finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (subdirectory) { TraverseFile(value, container, subdirectory); } } else { container.push_back(value); } } while (FindNextFile(hFind, &finder)); #else DIR * dir = opendir(path.c_str()); if (dir == nullptr) { throw std::runtime_error("No such file or directory : [" + path + "]"); } struct dirent * dirEvent = readdir(dir); while (dirEvent) { if (dirEvent->d_name[0] != '.') { std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + dirEvent->d_name; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + dirEvent->d_name; } if (IsDirectory(value)) { if (subdirectory) { TraverseFile(value, container, subdirectory); } } else { container.push_back(value); } } dirEvent = readdir(dir); } closedir(dir); #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 遍历文件 * * @param path 待遍历根目录路径 * @param container 文件结果容器 * @param rule 遍历规则 * @param subdirectory 是否遍历子目录 * */ void Filesystem::TraverseFile(const std::string & path, std::vector<std::string> & container, const std::regex & rule, bool subdirectory) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS std::string dir{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { dir = path + "*.*"; } else { dir = path + TINY_TOOLKIT_FOLDER_SEP + "*.*"; } WIN32_FIND_DATA finder{ }; HANDLE hFind = FindFirstFile(dir.c_str(), &finder); if (hFind == INVALID_HANDLE_VALUE) { throw std::runtime_error("No such file or directory : [" + path + "]"); } do { if (strcmp(finder.cFileName, ".") == 0 || strcmp(finder.cFileName, "..") == 0) { continue; } std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + finder.cFileName; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + finder.cFileName; } if (finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (subdirectory) { TraverseFile(value, container, rule, subdirectory); } } else { if (std::regex_match(value, rule)) { container.push_back(value); } } } while (FindNextFile(hFind, &finder)); #else DIR * dir = opendir(path.c_str()); if (dir == nullptr) { throw std::runtime_error("No such file or directory : [" + path + "]"); } struct dirent * dirEvent = readdir(dir); while (dirEvent) { if (dirEvent->d_name[0] != '.') { std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + dirEvent->d_name; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + dirEvent->d_name; } if (IsDirectory(value)) { if (subdirectory) { TraverseFile(value, container, rule, subdirectory); } } else { if (std::regex_match(value, rule)) { container.push_back(value); } } } dirEvent = readdir(dir); } closedir(dir); #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 遍历文件 * * @param path 待遍历根目录路径 * @param subdirectory 是否遍历子目录 * * @return 文件结果容器 * */ std::vector<std::string> Filesystem::TraverseFile(const std::string & path, bool subdirectory) { std::vector<std::string> container; TraverseFile(path, container, subdirectory); return container; } /** * * 遍历文件 * * @param path 待遍历根目录路径 * @param subdirectory 是否遍历子目录 * @param rule 遍历规则 * * @return 文件结果容器 * */ std::vector<std::string> Filesystem::TraverseFile(const std::string & path, const std::regex & rule, bool subdirectory) { std::vector<std::string> container; TraverseFile(path, container, rule, subdirectory); return container; } /** * * 遍历目录 * * @param path 待遍历根目录路径 * @param container 目录结果容器 * @param subdirectory 是否遍历子目录 * */ void Filesystem::TraverseDirectory(const std::string & path, std::vector<std::string> & container, bool subdirectory) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS std::string dir{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { dir = path + "*.*"; } else { dir = path + TINY_TOOLKIT_FOLDER_SEP + "*.*"; } WIN32_FIND_DATA finder{ }; HANDLE hFind = FindFirstFile(dir.c_str(), &finder); if (hFind == INVALID_HANDLE_VALUE) { throw std::runtime_error("No such file or directory : [" + path + "]"); } do { if (strcmp(finder.cFileName, ".") == 0 || strcmp(finder.cFileName, "..") == 0) { continue; } std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + finder.cFileName; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + finder.cFileName; } if (finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { container.push_back(value); if (subdirectory) { TraverseDirectory(value, container, subdirectory); } } } while (FindNextFile(hFind, &finder)); #else DIR * dir = opendir(path.c_str()); if (dir == nullptr) { throw std::runtime_error("No such file or directory : [" + path + "]"); } struct dirent * dirEvent = readdir(dir); while (dirEvent) { if (dirEvent->d_name[0] != '.') { std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + dirEvent->d_name; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + dirEvent->d_name; } if (IsDirectory(value)) { container.push_back(value); if (subdirectory) { TraverseDirectory(value, container, subdirectory); } } } dirEvent = readdir(dir); } closedir(dir); #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 遍历目录 * * @param path 待遍历根目录路径 * @param container 目录结果容器 * @param rule 遍历规则 * @param subdirectory 是否遍历子目录 * */ void Filesystem::TraverseDirectory(const std::string & path, std::vector<std::string> & container, const std::regex & rule, bool subdirectory) { #if TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS std::string dir{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { dir = path + "*.*"; } else { dir = path + TINY_TOOLKIT_FOLDER_SEP + "*.*"; } WIN32_FIND_DATA finder{ }; HANDLE hFind = FindFirstFile(dir.c_str(), &finder); if (hFind == INVALID_HANDLE_VALUE) { throw std::runtime_error("No such file or directory : [" + path + "]"); } do { if (strcmp(finder.cFileName, ".") == 0 || strcmp(finder.cFileName, "..") == 0) { continue; } std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + finder.cFileName; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + finder.cFileName; } if (finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (std::regex_match(value, rule)) { container.push_back(value); } if (subdirectory) { TraverseDirectory(value, container, rule, subdirectory); } } } while (FindNextFile(hFind, &finder)); #else DIR * dir = opendir(path.c_str()); if (dir == nullptr) { throw std::runtime_error("No such file or directory : [" + path + "]"); } struct dirent * dirEvent = readdir(dir); while (dirEvent) { if (dirEvent->d_name[0] != '.') { std::string value{ }; if (path[path.size() - 1] == TINY_TOOLKIT_FOLDER_SEP[0]) { value = path + dirEvent->d_name; } else { value = path + TINY_TOOLKIT_FOLDER_SEP + dirEvent->d_name; } if (IsDirectory(value)) { if (std::regex_match(value, rule)) { container.push_back(value); } if (subdirectory) { TraverseDirectory(value, container, rule, subdirectory); } } } dirEvent = readdir(dir); } closedir(dir); #endif // TINY_TOOLKIT_PLATFORM == TINY_TOOLKIT_PLATFORM_WINDOWS } /** * * 遍历目录 * * @param path 待遍历根目录路径 * @param subdirectory 是否遍历子目录 * * @return 目录结果容器 * */ std::vector<std::string> Filesystem::TraverseDirectory(const std::string & path, bool subdirectory) { std::vector<std::string> container; TraverseDirectory(path, container, subdirectory); return container; } /** * * 遍历目录 * * @param path 待遍历根目录路径 * @param rule 遍历规则 * @param subdirectory 是否遍历子目录 * * @return 目录结果容器 * */ std::vector<std::string> Filesystem::TraverseDirectory(const std::string & path, const std::regex & rule, bool subdirectory) { std::vector<std::string> container; TraverseDirectory(path, container, rule, subdirectory); return container; } }
|
---|