文件压缩处理(一)

文件压缩使用的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);
            }
        }
    }
};
相关推荐
孙启超31 分钟前
【AI开发之Rust】第 3 课:字符串与复合类型 —— 数据怎么放
开发语言·人工智能·后端·rust·llm·transformer
t-think36 分钟前
C++ string 类(上)—— string类初识与常用接口详解
开发语言·c++
cpp_learners1 小时前
C++ 实现责任链模式(Chain of Responsibility):从一堆 if-else 到可插拔的处理管道
开发语言·c++·责任链模式
君顾11 小时前
外卖CPS软件开发实战:从系统架构到部署全流程指南
java·开发语言·外卖
AIFQuant1 小时前
Python实时外汇行情接入实战:WebSocket与REST K线查询
开发语言·python·websocket
名字还没想好☜2 小时前
Java NIO ByteBuffer 实战:flip/clear/compact 三个绕晕人的方法与 position/limit 心智模型
java·开发语言·后端·spring·nio
小溪学编程2 小时前
AQS 原理详解:从 CLH 队列到 ReentrantLock 的实现
java·开发语言
持敬chijing2 小时前
Web前后端开发-JavaScript 入门教程
开发语言·前端·javascript
2601_966949652 小时前
从轮询到策略消费:量化系统如何高效处理五档盘口数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash