文件压缩处理(一)

文件压缩使用的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);
            }
        }
    }
};
相关推荐
智算菩萨1 分钟前
【Python自然语言处理】基于NLTK库的英文文本词频统计系统实现原理及应用
开发语言·python·自然语言处理
superman超哥4 分钟前
Rust 异步并发核心:tokio::spawn 与任务派发机制深度解析
开发语言·rust·编程语言·rust异步并发核心·rust任务派发机制
喵星人工作室4 分钟前
C++传说:神明之剑0.2.1
开发语言·c++·游戏
黎雁·泠崖5 分钟前
Java入门之吃透基础语法:注释+关键字+字面量+变量全解析
java·开发语言·intellij-idea·intellij idea
Ashley_Amanda8 分钟前
Python 常见问题梳理
开发语言·windows·python
UpgradeLink11 分钟前
基于 Go 打造的升级链路管理平台:upgradelink 让设备升级更简单
开发语言·后端·golang
天府之绝13 分钟前
uniapp 中使用uview表单验证时,自定义扩展的表单,在改变时无法触发表单验证处理;
开发语言·前端·javascript·vue.js·uni-app
萧鼎22 分钟前
深入解析 Python 的 Word 模板引擎:docxtpl 全面指南
开发语言·python·word
Chan1624 分钟前
场景题:如何设计一个分布式ID
java·开发语言·spring boot·java-ee·intellij-idea
chamu9930 分钟前
C++ 的可调用对象
开发语言·c++