文件压缩处理(一)

文件压缩使用的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);
            }
        }
    }
};
相关推荐
Chrikk2 小时前
现代化 C++ 工程构建:CMake 与包管理器的依赖治理
开发语言·c++
世转神风-3 小时前
qt-kits-警告:No C++ compiler,无法正常解析工程项目.pro文件
开发语言·c++
翔云 OCR API3 小时前
承兑汇票识别接口技术解析与应用实践
开发语言·人工智能·python·计算机视觉·ocr
元周民3 小时前
matlab求两个具有共根的多项式的所有共根(未详细验证)
开发语言·matlab
不忘不弃4 小时前
十进制数转换为二进制数
开发语言
csbysj20204 小时前
jQuery Mobile 触摸事件
开发语言
代码村新手4 小时前
C++-入门
开发语言·c++
神舟之光4 小时前
VSCode编译运行C/C++程序问题及解决方法
开发语言·c++
坐怀不乱杯魂4 小时前
C++ STL unordered_map/set 实现
开发语言·c++