#include <iostream>
#include <vector>
#include <string>
// 引入核心压缩解压头文件(之前的完整代码保存为 HuffmanCompress.h)
#include "HuffmanCompress.h"
// Windows 原生 API 头文件
#include <windows.h>
#include <commdlg.h>
#include <shlobj.h>
#pragma comment(lib, "comdlg32.lib")
#pragma comment(lib, "shell32.lib")
// -------------------------- 文件/文件夹选择函数(ANSI 版本,无宽字符串)--------------------------
std::string selectSingleFile(const std::string& filter) {
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAMEA);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter.c_str();
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA(&ofn)) {
return std::string(ofn.lpstrFile);
}
return "";
}
std::vector<std::string> selectMultipleFiles(const std::string& filter) {
std::vector<std::string> fileNames;
OPENFILENAMEA ofn;
CHAR szFile[1024 * 10] = { 0 };
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAMEA);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter.c_str();
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
if (GetOpenFileNameA(&ofn)) {
CHAR* p = szFile;
std::string folder = p;
p += strlen(p) + 1;
while (*p) {
std::string filePath = folder + "\\" + p;
fileNames.push_back(filePath);
p += strlen(p) + 1;
}
if (fileNames.empty()) {
fileNames.push_back(folder);
}
}
return fileNames;
}
std::string selectDirectory(const std::string& title = "选择目录") {
BROWSEINFOA bi = { 0 };
bi.lpszTitle = title.c_str();
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
LPITEMIDLIST pidl = SHBrowseForFolderA(&bi);
if (pidl != NULL) {
CHAR szPath[MAX_PATH] = { 0 };
if (SHGetPathFromIDListA(pidl, szPath)) {
CoTaskMemFree(pidl);
return std::string(szPath);
}
CoTaskMemFree(pidl);
}
return "";
}
std::string selectSaveFile(const std::string& defaultExt, const std::string& filter) {
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAMEA);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter.c_str();
ofn.nFilterIndex = 1;
ofn.lpstrDefExt = defaultExt.c_str();
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
if (GetSaveFileNameA(&ofn)) {
return std::string(ofn.lpstrFile);
}
return "";
}
// -------------------------- 菜单和辅助函数 --------------------------
void showMenu() {
system("cls");
std::cout << "\n===== 哈夫曼压缩解压工具 =====" << std::endl;
std::cout << "1. 压缩单个文件" << std::endl;
std::cout << "2. 压缩多个文件(按住Ctrl多选)" << std::endl;
std::cout << "3. 压缩文件夹(遍历所有文件)" << std::endl;
std::cout << "4. 解压缩文件(支持.huf/.zip/.rar/.7z)" << std::endl;
std::cout << "0. 退出程序" << std::endl;
std::cout << "==============================" << std::endl;
std::cout << "请选择操作(输入数字): ";
}
bool pathExists(const std::string& path) {
return re::exists(path);
}
bool createDirRecursive(const std::string& path) {
try {
return re::create_directories(path);
}
catch (...) {
return false;
}
}
// -------------------------- 主函数(彻底修复 cin.ignore 问题)--------------------------
int main() {
File_faction huffmanTool;
int choice;
do {
showMenu();
std::cin >> choice;
// 核心修复:用固定大数值替代 numeric_limits,无需额外头文件
std::cin.ignore(10000, '\n'); // 忽略最多10000个字符(足够覆盖控制台输入)
switch (choice) {
case 1: // 压缩单个文件
{
std::string inputFile = selectSingleFile("所有文件 (*.*)\0*.*\0");
if (inputFile.empty()) {
std::cout << "未选择任何文件,返回菜单..." << std::endl;
system("pause");
break;
}
std::string outputFile = selectSaveFile("huf", "哈夫曼压缩文件 (*.huf)\0*.huf\0所有文件 (*.*)\0*.*\0");
if (outputFile.empty()) {
std::cout << "未选择保存路径,返回菜单..." << std::endl;
system("pause");
break;
}
huffmanTool.setParams({ inputFile }, { outputFile }, true);
huffmanTool.decide();
system("pause");
}
break;
case 2: // 压缩多个文件
{
std::vector<std::string> inputFiles = selectMultipleFiles("所有文件 (*.*)\0*.*\0");
if (inputFiles.empty()) {
std::cout << "未选择任何文件,返回菜单..." << std::endl;
system("pause");
break;
}
std::string outputFile = selectSaveFile("huf", "哈夫曼压缩文件 (*.huf)\0*.huf\0所有文件 (*.*)\0*.*\0");
if (outputFile.empty()) {
std::cout << "未选择保存路径,返回菜单..." << std::endl;
system("pause");
break;
}
huffmanTool.setParams(inputFiles, { outputFile }, true);
huffmanTool.decide();
system("pause");
}
break;
case 3: // 压缩文件夹
{
std::string inputDir = selectDirectory("选择要压缩的文件夹");
if (inputDir.empty()) {
std::cout << "未选择文件夹,返回菜单..." << std::endl;
system("pause");
break;
}
std::string outputFile = selectSaveFile("huf", "哈夫曼压缩文件 (*.huf)\0*.huf\0所有文件 (*.*)\0*.*\0");
if (outputFile.empty()) {
std::cout << "未选择保存路径,返回菜单..." << std::endl;
system("pause");
break;
}
huffmanTool.setParams({ inputDir }, { outputFile }, true);
huffmanTool.decide();
system("pause");
}
break;
case 4: // 解压缩文件
{
std::string inputFile = selectSingleFile("压缩包文件 \0*.\0所有文件 (*.*)\0*.*\0");
if (inputFile.empty()) {
std::cout << "未选择压缩包,返回菜单..." << std::endl;
system("pause");
break;
}
std::string outputDir = selectDirectory("选择解压目标文件夹");
if (outputDir.empty()) {
std::cout << "未选择解压路径,返回菜单..." << std::endl;
system("pause");
break;
}
if (!pathExists(outputDir) && !createDirRecursive(outputDir)) {
std::cout << "创建解压文件夹失败,返回菜单..." << std::endl;
system("pause");
break;
}
huffmanTool.setParams({ inputFile }, { outputDir }, false);
huffmanTool.decide();
system("pause");
}
break;
case 0: // 退出
std::cout << "感谢使用,再见!" << std::endl;
system("pause");
break;
default: // 无效选择
std::cout << "无效的选择,请重新输入!" << std::endl;
system("pause");
break;
}
} while (choice != 0);
return 0;
}#pragma once
#include <unordered_map>
#include <filesystem>
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <cstdint>
#include <system_error>
#include <limits>
namespace re = std::filesystem;
#include <bitset>
struct Node {
uint8_t data;
int frea;
Node* left;
Node* right;
Node(uint8_t a, int b) : data(a), frea(b), left(nullptr), right(nullptr) {}
};
struct Queue_rule {
bool operator()(Node* a, Node* b) {
return a->frea > b->frea;
}
};
class Tool {
public:
static void get_codes(Node* root, std::string str, std::unordered_map<uint8_t, std::string>& codes) {
if (!root) return;
if (!root->left && !root->right) {
codes[root->data] = str.empty() ? "0" : str;
return;
}
get_codes(root->left, str + '0', codes);
get_codes(root->right, str + '1', codes);
}
static Node* Hafuman_Tree(std::unordered_map<uint8_t, int> rep) {
std::priority_queue<Node*, std::vector<Node*>, Queue_rule> minnode;
for (const auto& p : rep) minnode.push(new Node(p.first, p.second));
while (minnode.size() != 1) {
Node* left = minnode.top();
minnode.pop();
Node* right = minnode.top();
minnode.pop();
Node* top = new Node('#', left->frea + right->frea);
top->left = left;
top->right = right;
minnode.push(top);
}
return minnode.top();
}
static std::unordered_map<uint8_t, int> getdata(std::vector<std::string> inpath) {
std::unordered_map<uint8_t, int> frea;
for (const auto& path : inpath) {
std::ifstream in(path, std::ios::binary);
if (!in) {
std::cerr << "警告:文件 " << path << " 无法打开,跳过该文件" << std::endl;
continue;
}
uint8_t bt;
while (in.read(reinterpret_cast<char*>(&bt), 1)) frea[bt]++;
in.close();
}
return frea;
}
static uint64_t getFileSize(const std::string& path) {
try {
return re::file_size(path);
}
catch (const std::exception& e) {
std::cerr << "警告:文件 " << path << " 大小获取失败,返回 0。错误:" << e.what() << std::endl;
return 0;
}
}
static std::vector<std::string> traverseFolder(const std::string& folderPath, const std::set<std::string>& filterExt = {}) {
std::vector<std::string> filePaths;
try {
if (!re::exists(folderPath)) {
std::cerr << "错误:" << folderPath << " 路径不存在" << std::endl;
return filePaths;
}
if (!re::is_directory(folderPath)) {
std::cerr << "错误:" << folderPath << " 不是有效文件夹" << std::endl;
return filePaths;
}
for (const auto& entry : re::recursive_directory_iterator(folderPath)) {
if (re::is_regular_file(entry.path())) {
std::string filePath = entry.path().string();
if (filterExt.empty()) {
filePaths.push_back(filePath);
}
else {
std::string ext = entry.path().extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (filterExt.count(ext)) {
filePaths.push_back(filePath);
}
}
}
}
}
catch (const std::exception& e) {
std::cerr << "错误:遍历文件夹 " << folderPath << " 失败。错误:" << e.what() << std::endl;
}
return filePaths;
}
static bool isCompressedFile(const std::string& filePath) {
std::set<std::string> compressedExt = { ".huf", ".zip", ".rar", ".7z" };
try {
std::string ext = re::path(filePath).extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return compressedExt.count(ext) > 0;
}
catch (const std::exception& e) {
std::cerr << "警告:解析文件 " << filePath << " 后缀失败。错误:" << e.what() << std::endl;
return false;
}
}
static std::string cleanFileName(const std::string& fileName) {
std::string illegalChars = R"(:*?"<>|\/)";
std::string cleaned = fileName;
for (char c : illegalChars) {
std::replace(cleaned.begin(), cleaned.end(), c, '_');
}
return cleaned;
}
static int getMaxCodeLength(const std::unordered_map<uint8_t, std::string>& codes) {
int maxLen = 0;
for (const auto& p : codes) {
maxLen = std::max(maxLen, static_cast<int>(p.second.size()));
}
return maxLen;
}
};
class File_faction {
private:
std::vector<std::string> inpath;
std::vector<std::string> outpath;
bool isCompressMode;
public:
void setParams(const std::vector<std::string>& inPaths, const std::vector<std::string>& outPaths, bool compressMode) {
inpath = inPaths;
outpath = outPaths;
isCompressMode = compressMode;
}
bool compress(std::vector<std::string> path1, std::string outpath) {
if (path1.empty()) {
std::cerr << "错误:压缩文件列表为空" << std::endl;
return false;
}
auto freq = Tool::getdata(path1);
if (freq.empty()) {
std::cerr << "错误:所有输入文件无有效数据" << std::endl;
return false;
}
Node* root = Tool::Hafuman_Tree(freq);
std::unordered_map<uint8_t, std::string> codes;
Tool::get_codes(root, "", codes);
int maxCodeLen = Tool::getMaxCodeLength(codes);
delete root;
std::ofstream out(outpath, std::ios::binary | std::ios::trunc);
if (!out) {
std::cerr << "错误:无法创建输出文件 " << outpath << std::endl;
return false;
}
int codesize = codes.size();
out.write(reinterpret_cast<char*>(&codesize), sizeof(codesize));
out.write(reinterpret_cast<char*>(&maxCodeLen), sizeof(maxCodeLen));
for (const auto& p : codes) {
uint8_t bt = p.first;
std::string code = p.second;
int len = code.size();
out.write(reinterpret_cast<char*>(&bt), 1);
out.write(reinterpret_cast<char*>(&len), sizeof(len));
std::bitset<8> bits;
int bitCount = 0;
for (char c : code) {
bits[7 - (bitCount % 8)] = (c == '1');
bitCount++;
if (bitCount % 8 == 0 || bitCount == len) {
out.put(static_cast<char>(bits.to_ulong()));
bits.reset();
}
}
}
uint64_t totalSize = 0;
for (const auto& path : path1) totalSize += Tool::getFileSize(path);
out.write(reinterpret_cast<char*>(&totalSize), sizeof(totalSize));
for (const auto& path : path1) {
re::path filePathObj(path);
std::string fileName = filePathObj.filename().string();
uint64_t fileSize = Tool::getFileSize(path);
int fileNameLen = fileName.size();
out.write(reinterpret_cast<char*>(&fileNameLen), sizeof(fileNameLen));
out.write(fileName.c_str(), fileNameLen);
out.write(reinterpret_cast<char*>(&fileSize), sizeof(fileSize));
std::ifstream in(path, std::ios::binary);
if (!in) {
std::cerr << "警告:文件 " << path << " 无法打开,跳过" << std::endl;
continue;
}
std::bitset<8> bits;
int bitCount = 0;
uint8_t bt;
while (in.read(reinterpret_cast<char*>(&bt), 1)) {
std::string code = codes[bt];
for (char c : code) {
bits[7 - (bitCount % 8)] = (c == '1');
bitCount++;
if (bitCount == 8) {
out.put(static_cast<char>(bits.to_ulong()));
bits.reset();
bitCount = 0;
}
}
}
if (bitCount > 0) {
out.put(static_cast<char>(bits.to_ulong()));
}
in.close();
}
out.close();
std::cout << "压缩完成!输出文件:" << outpath << ",总原始大小:" << totalSize << " 字节" << std::endl;
return true;
}
bool decompress(std::vector<std::string> path1, std::vector<std::string> path2) {
if (path1.empty() || path2.empty()) {
std::cerr << "错误:输入路径或输出路径为空" << std::endl;
return false;
}
std::string inPath = path1.front();
std::string outFolder = path2.front();
try {
if (!re::exists(outFolder)) {
std::cout << "创建解压文件夹:" << outFolder << std::endl;
re::create_directories(outFolder);
}
// 修复核心:path对象显式转换为string
std::string testFile = (re::path(outFolder) / ".test_write_perm").string();
std::ofstream testOut(testFile);
if (!testOut) {
std::cerr << "错误:解压文件夹 " << outFolder << " 无写入权限" << std::endl;
return false;
}
testOut.close();
re::remove(re::path(testFile)); // 移除时也可直接用string,但显式转换更规范
}
catch (const std::exception& e) {
std::cerr << "错误:创建解压文件夹失败。错误:" << e.what() << std::endl;
return false;
}
std::ifstream in(inPath, std::ios::binary);
if (!in) {
std::cerr << "错误:无法打开压缩包 " << inPath << std::endl;
return false;
}
int codesize;
if (!in.read(reinterpret_cast<char*>(&codesize), sizeof(codesize))) {
std::cerr << "错误:压缩包损坏,无法读取编码表大小" << std::endl;
in.close();
return false;
}
int maxCodeLen;
if (!in.read(reinterpret_cast<char*>(&maxCodeLen), sizeof(maxCodeLen))) {
std::cerr << "错误:压缩包损坏,无法读取最大编码长度" << std::endl;
in.close();
return false;
}
if (maxCodeLen <= 0 || maxCodeLen > 1024) {
std::cerr << "错误:无效的最大编码长度 " << maxCodeLen << ",压缩包可能损坏" << std::endl;
in.close();
return false;
}
std::unordered_map<std::string, uint8_t> codes;
for (int i = 0; i < codesize; ++i) {
uint8_t bt;
int len;
if (!in.read(reinterpret_cast<char*>(&bt), sizeof(bt)) ||
!in.read(reinterpret_cast<char*>(&len), sizeof(len))) {
std::cerr << "错误:编码表读取失败" << std::endl;
in.close();
return false;
}
if (len <= 0 || len > maxCodeLen) {
std::cerr << "错误:无效的编码长度 " << len << ",压缩包可能损坏" << std::endl;
in.close();
return false;
}
std::string code;
int bytes = (len + 7) / 8;
for (int j = 0; j < bytes; ++j) {
uint8_t b;
if (!in.read(reinterpret_cast<char*>(&b), 1)) {
std::cerr << "错误:压缩包损坏,编码内容读取失败" << std::endl;
in.close();
return false;
}
std::bitset<8> bits(b);
for (int k = 7; k >= 0 && code.size() < len; --k) { // 从高位(7)到低位(0)读取
code += bits[k] ? "1" : "0";
}
}
codes[code] = bt;
}
uint64_t totalSize;
if (!in.read(reinterpret_cast<char*>(&totalSize), sizeof(totalSize))) {
std::cerr << "错误:无法读取总文件大小" << std::endl;
in.close();
return false;
}
int bitpos = 0;
uint8_t bitbu = 0;
std::string curcode;
uint64_t totalDecodedSize = 0;
const int MAX_STRING_LEN = std::numeric_limits<std::string::size_type>::max() / 2;
while (true) {
if (in.peek() == EOF) break;
int fileNameLen;
if (!in.read(reinterpret_cast<char*>(&fileNameLen), sizeof(fileNameLen))) {
std::cerr << "错误:文件名长度读取失败" << std::endl;
break;
}
if (fileNameLen < 0 || fileNameLen > 4096) {
std::cerr << "错误:无效的文件名长度 " << fileNameLen << ",压缩包可能损坏" << std::endl;
break;
}
std::string fileName(fileNameLen, '\0');
if (!in.read(&fileName[0], fileNameLen)) {
std::cerr << "错误:文件名读取失败" << std::endl;
break;
}
std::string cleanedFileName = Tool::cleanFileName(fileName);
uint64_t fileSize;
if (!in.read(reinterpret_cast<char*>(&fileSize), sizeof(fileSize))) {
std::cerr << "错误:文件 " << cleanedFileName << " 大小读取失败" << std::endl;
break;
}
if (fileSize > 1024ULL * 1024ULL * 1024ULL * 10) {
std::cerr << "错误:文件 " << cleanedFileName << " 大小超出限制(" << fileSize << " 字节)" << std::endl;
break;
}
re::path outPathObj;
try {
outPathObj = re::path(outFolder) / cleanedFileName;
}
catch (const std::exception& e) {
std::cerr << "错误:拼接输出路径失败(文件名:" << cleanedFileName << ")。错误:" << e.what() << std::endl;
continue;
}
std::string outPath = outPathObj.string();
std::ofstream out;
try {
out.open(outPath, std::ios::binary | std::ios::trunc);
}
catch (const std::exception& e) {
std::cerr << "错误:创建输出文件 " << outPath << " 失败。错误:" << e.what() << std::endl;
continue;
}
if (!out) {
std::cerr << "错误:无法打开输出文件 " << outPath << "(可能无权限)" << std::endl;
continue;
}
uint8_t writbuf[1024];
size_t bufsize = 0;
uint64_t decodedSize = 0;
while (decodedSize < fileSize) {
if (curcode.size() >= static_cast<size_t>(maxCodeLen)) {
std::cerr << "错误:文件 " << cleanedFileName << " 解压失败,编码匹配超时(可能压缩包损坏)" << std::endl;
decodedSize = fileSize;
out.close();
re::remove(outPathObj); // 直接用path对象删除,更高效
break;
}
if (curcode.size() >= MAX_STRING_LEN) {
std::cerr << "错误:文件 " << cleanedFileName << " 解压失败,字符串长度超出限制" << std::endl;
decodedSize = fileSize;
out.close();
re::remove(outPathObj);
break;
}
if (bitpos == 0) {
if (!in.read(reinterpret_cast<char*>(&bitbu), sizeof(bitbu))) {
std::cerr << "错误:压缩包损坏,文件 " << cleanedFileName << " 数据不完整" << std::endl;
decodedSize = fileSize;
out.close();
re::remove(outPathObj);
break;
}
bitpos = 8;
}
bitpos--;
bool bit = (bitbu >> bitpos) & 1;
curcode += bit ? "1" : "0";
auto it = codes.find(curcode);
if (it != codes.end()) {
uint8_t decode = it->second;
writbuf[bufsize++] = decode;
decodedSize++;
totalDecodedSize++;
if (bufsize == 1024) {
out.write(reinterpret_cast<char*>(writbuf), bufsize);
bufsize = 0;
}
curcode.clear();
}
}
if (bufsize > 0 && decodedSize <= fileSize) {
out.write(reinterpret_cast<char*>(writbuf), bufsize);
}
out.close();
if (decodedSize == fileSize) {
std::cout << "文件 " << cleanedFileName << " 解压完成,大小:" << decodedSize << " 字节(预期:" << fileSize << " 字节)" << std::endl;
}
else {
std::cerr << "文件 " << cleanedFileName << " 解压失败,已删除损坏文件" << std::endl;
}
}
in.close();
if (totalDecodedSize == totalSize) {
std::cout << "所有文件解压完成!总解码大小:" << totalDecodedSize << " 字节(与原始大小一致)" << std::endl;
return true;
}
else {
std::cerr << "警告:解压数据不完整!总解码大小:" << totalDecodedSize << " 字节(原始大小:" << totalSize << " 字节)" << std::endl;
return false;
}
}
void single_file() {
if (inpath.empty() || outpath.empty()) {
std::cerr << "错误:单文件处理缺少输入/输出路径" << std::endl;
return;
}
std::string inPath = inpath.front();
std::string outPath = outpath.front();
if (isCompressMode) {
std::vector<std::string> singleFile = { inPath };
re::path outPathObj(outPath);
if (outPathObj.extension().empty()) {
outPath += ".huf";
}
compress(singleFile, outPath);
}
else {
if (re::is_directory(outPath)) {
decompress(inpath, { outPath });
}
else {
try {
re::path outPathObj(outPath);
re::create_directories(outPathObj.parent_path());
decompress(inpath, { outPathObj.parent_path().string() });
}
catch (const std::exception& e) {
std::cerr << "错误:创建输出文件夹失败。错误:" << e.what() << std::endl;
}
}
}
}
void Multiple_Files() {
if (inpath.empty() || outpath.empty()) {
std::cerr << "错误:多文件处理缺少输入/输出路径" << std::endl;
return;
}
std::string outPath = outpath.front();
if (isCompressMode) {
re::path outPathObj(outPath);
if (outPathObj.extension().empty()) {
outPath += ".huf";
}
compress(inpath, outPath);
}
else {
std::string outFolder = outPath;
try {
if (!re::exists(outFolder)) {
re::create_directories(outFolder);
}
}
catch (const std::exception& e) {
std::cerr << "错误:创建解压文件夹失败。错误:" << e.what() << std::endl;
return;
}
for (const auto& zipPath : inpath) {
if (Tool::isCompressedFile(zipPath)) {
decompress({ zipPath }, { outFolder });
}
else {
std::cerr << "警告:" << zipPath << " 不是压缩包,跳过" << std::endl;
}
}
}
}
void folder() {
if (inpath.empty() || outpath.empty()) {
std::cerr << "错误:文件夹处理缺少输入/输出路径" << std::endl;
return;
}
std::string inFolder = inpath.front();
std::string outPath = outpath.front();
if (isCompressMode) {
std::vector<std::string> allFiles = Tool::traverseFolder(inFolder);
if (allFiles.empty()) {
std::cerr << "错误:文件夹 " << inFolder << " 下无有效文件" << std::endl;
return;
}
re::path outPathObj(outPath);
if (outPathObj.extension().empty()) {
outPath += ".huf";
}
compress(allFiles, outPath);
}
else {
if (inpath.size() == 1) {
std::string zipPath = inpath.front();
if (Tool::isCompressedFile(zipPath)) {
decompress(inpath, { outPath });
}
else {
std::cerr << "错误:文件夹解压仅支持单个压缩包输入(当前输入不是压缩包)" << std::endl;
}
}
else {
std::cerr << "错误:文件夹解压仅支持单个压缩包输入(当前输入 " << inpath.size() << " 个路径)" << std::endl;
}
}
}
void decide() {
if (inpath.empty()) {
std::cerr << "错误:输入路径为空" << std::endl;
return;
}
int fileCount = 0;
int folderCount = 0;
int zipCount = 0;
std::vector<std::string> validFiles;
std::vector<std::string> validFolders;
for (const auto& path : inpath) {
try {
if (!re::exists(path)) {
std::cerr << "警告:路径 " << path << " 不存在,跳过" << std::endl;
continue;
}
if (re::is_regular_file(path)) {
fileCount++;
validFiles.push_back(path);
if (Tool::isCompressedFile(path)) {
zipCount++;
}
}
else if (re::is_directory(path)) {
folderCount++;
validFolders.push_back(path);
}
}
catch (const std::exception& e) {
std::cerr << "警告:路径 " << path << " 无效,跳过。错误:" << e.what() << std::endl;
continue;
}
}
if (folderCount > 0) {
inpath = { validFolders.front() };
}
else {
inpath = validFiles;
}
if (folderCount > 0) {
if (folderCount > 1) {
std::cerr << "警告:仅支持单个文件夹输入,取第一个文件夹" << std::endl;
}
folder();
return;
}
if (fileCount > 1) {
Multiple_Files();
return;
}
if (fileCount == 1) {
single_file();
return;
}
std::cerr << "错误:无有效输入文件/文件夹" << std::endl;
}
};
最新发布