文件压缩使用的bit7z库
将大写转换为小写
cpp
static std::string toLower(std::string_view str) noexcept {
std::string result;
result.reserve(str.size());
std::ranges::transform(str, std::back_inserter(result), [](unsigned char word) { return std::tolower(word); });
return result;
}
文件系统结构体
采用树状结构,节点信息包含路径以及文件名,用递归的方式将文件挂载在对应的父节点下
cpp
struct FileItem {
FileItem* parent = nullptr;
std::string filePath;
std::string fileName;
quint64 fileSize = 0;
quint64 modityTime = 0;
quint32 index = 0;
std::string extension;
std::vector<FileItem*> childs;
bool isDir = false;
FileItem() = default;
FileItem(FileItem* p_parent, std::string_view path, std::string_view name, quint64 size, quint64 time,
uint32_t u_index, std::string_view extension_str, const std::vector<FileItem*>& list, bool is_dir) noexcept
: parent(p_parent),
filePath(path),
fileName(name),
fileSize(size),
modityTime(time),
index(u_index),
extension(extension_str),
childs(list),
isDir(is_dir) {}
~FileItem() {
for (FileItem* child : childs) {
delete child;
}
childs.clear();
}
FileItem(FileItem&& other) noexcept
: parent(other.parent),
filePath(std::move(other.filePath)),
fileName(std::move(other.fileName)),
fileSize(other.fileSize),
modityTime(other.modityTime),
index(other.index),
extension(std::move(other.extension)),
childs(std::move(other.childs)),
isDir(other.isDir) {
for (auto* child : childs) {
if (child) {
child->parent = this;
}
}
other.childs.clear();
}
FileItem& operator=(FileItem&& other) noexcept {
if (this != &other) {
for (FileItem* child : childs) {
del(child);
}
childs.clear();
parent = other.parent;
filePath = std::move(other.filePath);
fileName = std::move(other.fileName);
fileSize = other.fileSize;
modityTime = other.modityTime;
index = other.index;
extension = std::move(other.extension);
childs = std::move(other.childs);
isDir = other.isDir;
for (auto* child : childs) {
if (child) {
child->parent = this;
}
}
other.childs.clear();
}
return *this;
}
FileItem(const FileItem&) = delete;
FileItem& operator=(const FileItem&) = delete;
void add(FileItem* pItem) noexcept {
std::string_view const item_name = pItem->fileName;
const std::string& item_path = pItem->filePath;
std::string const parent_path = item_path.substr(0, item_path.rfind(item_name));
if (parent_path.empty()) {
pItem->parent = this;
if (!find(item_name)) childs.push_back(pItem);
return;
}
if (parent_path.length() >= filePath.length() && parent_path.starts_with(filePath)) {
std::string child_path = parent_path.substr(filePath.size());
if (!child_path.empty() && (child_path[0] == '\\' || child_path[0] == '/')) {
child_path = child_path.substr(1);
}
if (child_path.empty()) {
pItem->parent = this;
childs.push_back(pItem);
return;
}
size_t const pos = child_path.find_first_of("\\/");
std::string const sub_dir = (pos != std::string::npos) ? child_path.substr(0, pos) : child_path;
for (auto* itr : childs) {
if (itr->fileName == sub_dir) {
itr->add(pItem);
return;
}
}
auto* child = new FileItem(
this, this->filePath + (this->filePath.empty() ? "" : "\\") + sub_dir, sub_dir, 0, 0, 0, "", {}, true
);
childs.push_back(child);
child->add(pItem);
}
}
void del(FileItem* pItem) {
if (!pItem) return;
auto itr = std::ranges::find(childs, pItem);
if (itr != childs.end()) {
delete pItem;
childs.erase(itr);
}
}
void sort(const std::function<bool(FileItem*, FileItem*)>& compare) noexcept {
std::ranges::partition(childs, [](FileItem* item) { return item->isDir; });
auto first_file_node = std::ranges::find_if_not(childs, [](FileItem* item) { return item->isDir; });
std::ranges::sort(childs.begin(), first_file_node, compare);
std::ranges::sort(first_file_node, childs.end(), compare);
}
void sortDefault() noexcept {
sort([](FileItem* left, FileItem* right) {
if (left->isDir && !right->isDir) return true;
if (!left->isDir && right->isDir) return false;
return true;
});
}
void sortByName(bool bAsc = true) {
sort([bAsc](FileItem* left, FileItem* right) {
return bAsc ? toLower(left->fileName) > toLower(right->fileName)
: toLower(left->fileName) < toLower(right->fileName);
});
}
void sortBySize(bool bAsc = true) {
sort([bAsc](FileItem* left, FileItem* right) {
return bAsc ? left->fileSize > right->fileSize : left->fileSize < right->fileSize;
});
}
void sortByType(bool bAsc = true) {
sort([bAsc](FileItem* left, FileItem* right) {
return bAsc ? toLower(left->extension) > toLower(right->extension)
: toLower(left->extension) < toLower(right->extension);
});
}
void sortByTime(bool bAsc = true) {
sort([bAsc](FileItem* left, FileItem* right) {
return bAsc ? left->modityTime > right->modityTime : left->modityTime < right->modityTime;
});
}
FileItem* find(std::string_view path) noexcept {
if (filePath == path) return this;
for (auto* child : childs) {
if (!child) continue;
if (FileItem* item = child->find(path)) {
return item;
}
}
return nullptr;
}
FileItem* find(uint32_t u_index) noexcept {
if (this->index == u_index && parent) return this;
for (auto* child : childs) {
if (!child) continue;
if (FileItem* item = child->find(u_index)) {
return item;
}
}
return nullptr;
}
void printTree(int depth = 0) const {
std::stringstream out;
for (int i = 0; i < depth; ++i) {
out << "\t";
}
// 打印当前节点信息
out << filePath << "--" << index << "\n";
spdlog::debug(out.str());
// 递归打印子节点
for (const auto* child : childs) {
if (child) {
child->printTree(depth + 1);
}
}
}
};