[C++] bitset 按字节解析为std::string

#include <iostream>
#include <string>
#include <cstring>
#include <bitset>

int main() {
    // 假设 4 个 char 存储了 32 位的 1
    //char charArray[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
    char charArray[4] = { 0x41, 0x42, 0x43, 0x44 };  // 对应字符 'A', 'B', 'C', 'D'

    // 将 char 数组转换为 std::string
    std::string str(charArray, 4);

    // 打印字符串的每个字符的十六进制值
    for (unsigned char c : str) {
        std::cout << std::hex << static_cast<int>(c) << " ";
    }
    std::cout << std::endl;
    std::cout << str << std::endl;// ABCD


    // 将 charArray 转换为 32 位的 bitset
    std::bitset<32> bitset3;
    for (int i = 0; i < 4; ++i) {
        std::bitset<8> charBits(charArray[i]);
        for (int j = 0; j < 8; ++j) {
            bitset3[i * 8 + j] = charBits[j];
        }
    }

    // 打印 bitset
    std::cout << "bitset: " << bitset3 << std::endl;

    // 假设我们有一个 32 位的 bitset
    std::bitset<32> bitset2("01000100010000110100001001000001");  // 示例 bitset

    // 将 bitset 转换为字符串
    std::string bitsetString = bitset2.to_string();

    // 打印字符串
    std::cout << "bitset as string: " << bitsetString << std::endl;

    // 假设我们有一个 32 位的 bitset
    std::bitset<32> bitset("01000100010000110100001001000001");  // 示例 bitset

    // 将 bitset 按 8 位解析为 4 个字节的 std::string
    std::string byteString;
    for (int i = 0; i < 32; i += 8) {
        std::bitset<8> byteBits;
        for (int j = 0; j < 8; ++j) {
            byteBits[j] = bitset[i + j];
        }
        char byte = static_cast<char>(byteBits.to_ulong());
        byteString.push_back(byte);
    }

    // 打印结果
    std::cout << "byteString: " << byteString << std::endl;

    // 打印每个字符的十六进制值
    for (unsigned char c : byteString) {
        std::cout << std::hex << static_cast<int>(c) << " ";
    }
    std::cout << std::endl;


    return 0;
}

41 42 43 44
ABCD
bitset: 01000100010000110100001001000001
bitset as string: 01000100010000110100001001000001
byteString: ABCD
41 42 43 44

#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; } };
最新发布
11-26
Mian.cpp #include "utils.hpp" #include <iostream> #include <string> #include <chrono> #include <thread> int main() { OutputRuleMapper mapper; while (true) { std::string input; std::cout << "请输入一个八字节的十六进制字符串(例如:123456789ABCDEF0)或输入'exit'退出: "; std::cin >> input; if (input == "exit") { std::cout << "程序已退出。" << std::endl; break; } if (input.length() != 16) { std::cerr << "输入长度不正确,必须为16个字符(8字节)" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(12)); clearScreen(); continue; } processInput(input, mapper); std::cout << "\n等待12秒后开始新一轮输入..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(12)); clearScreen(); } return 0; } output_rule_mapper.cpp #include "output_rule_mapper.hpp" OutputRuleMapper::OutputRuleMapper() { outputRules = { {"00000000", "."}, {"00000001", ".."}, {"00000010", "..."}, {"00000011", "...."}, {"00000100", "....."} }; } std::string OutputRuleMapper::getOutput(const std::string& binaryStr) { auto it = outputRules.find(binaryStr); return it != outputRules.end() ? it->second : ""; } Utils.cpp #include "utils.hpp" #include <sstream> #include <bitset> #include <iostream> #include <thread> #include <chrono> #include <cstdlib> std::string hexToBinary(const std::string& hexByte) { if (hexByte.length() != 2) return ""; std::stringstream ss; unsigned int byteValue; ss << std::hex << hexByte; ss >> byteValue; return std::bitset<8>(byteValue).to_string(); } void clearScreen() { #ifdef _WIN32 system("cls"); #else system("clear"); #endif } void processInput(const std::string& input, OutputRuleMapper& mapper) { for (size_t i = 0; i < input.length(); i += 2) { std::string hexByte = input.substr(i, 2); std::string binaryStr = hexToBinary(hexByte); std::string output = mapper.getOutput(binaryStr); std::cout << "Hex: " << hexByte << " -> Binary: " << binaryStr; if (!output.empty()) { std::cout << " -> Output: " << output << std::endl; } else { std::cout << " -> No matching rule found." << std::endl; } } } output_rule_mapper.hpp #ifndef OUTPUT_RULE_MAPPER_HPP #define OUTPUT_RULE_MAPPER_HPP #include <string> #include <unordered_map> class OutputRuleMapper { private: std::unordered_map<std::string, std::string> outputRules; public: OutputRuleMapper(); std::string getOutput(const std::string& binaryStr); }; #endif Utils.hpp #ifndef UTILS_HPP #define UTILS_HPP #include <string> #include "output_rule_mapper.hpp" std::string hexToBinary(const std::string& hexByte); void clearScreen(); void processInput(const std::string& input, OutputRuleMapper& mapper); #endif 这是我在VSCODE上用C++写的代码,现在我需要在unity上用C#实现,请你帮我变下代码
07-30
class SingleFileCompressor : public ICompressor { private: std::unordered_map<uint8_t, int> countFreq(const std::string& filePath) { std::unordered_map<uint8_t, int> freq; std::ifstream in(filePath, std::ios::binary);//二进制读取 if (!in) { std::cerr << "错误:读取文件失败 " << filePath << std::endl; exit(1); } uint8_t byte; while (in.read(reinterpret_cast<char*>(&byte), 1)) { freq[byte]++; } in.close(); return freq;//返回读取的文件数据流 } Node* buildTree(std::unordered_map<uint8_t, int>& freq) { std::priority_queue<Node*, std::vector<Node*>, CompareNode> minHeap; for (const auto& p : freq) { minHeap.push(new Node(p.first, p.second)); } while (minHeap.size() > 1) { auto left = minHeap.top(); minHeap.pop(); auto right = minHeap.top(); minHeap.pop(); minHeap.push(new Node(left, right)); } return minHeap.empty() ? nullptr : minHeap.top(); } void generateCodes(Node* root, std::string code, std::unordered_map<uint8_t, std::string>& codes) { if (!root) return; if (!root->left && !root->right) { codes[root->data] = code.empty() ? "0" : code; return; } generateCodes(root->left, code + "0", codes); generateCodes(root->right, code + "1", codes); } public: bool compress(const std::string& inputPath, const std::string& outputPath) override { if (!FileUtils::pathExists(inputPath)) { std::cerr << "错误:输入文件不存在 " << inputPath << std::endl; return false; } if (FileUtils::isDirectory(inputPath)) { std::cerr << "错误:输入路径是目录,单文件压缩仅支持文件" << std::endl; return false; } std::string fileName = FileUtils::getFileName(inputPath);//获取文件名 auto freq = countFreq(inputPath); if (freq.empty()) { std::cout << "警告:文件 " << fileName << " 为空" << std::endl; ProgressUtils::updateFileProgress(fileName, 0, 0, "文件压缩"); return true; } auto root = buildTree(freq);//建立哈夫曼树 std::unordered_map<uint8_t, std::string> codes; generateCodes(root, "", codes);//通过已经建立的哈夫曼树,创建每个节点的哈夫曼编码 delete root; // 进度配置:强制逐块更新,小文件也能看到进度 uint64_t fileTotal = FileUtils::getFileSize(inputPath); uint64_t fileCompleted = 0; const uint32_t BUF_SIZE = 1024; // 1KB块 std::cout << "\n开始压缩:" << fileName << "(总大小:" << fileTotal << " B)" << std::endl; std::ofstream out(outputPath, std::ios::binary); if (!out) { std::cerr << "错误:无法创建输出文件 " << outputPath << std::endl; return false; } // 写入编码表 int codeSize = codes.size(); out.write(reinterpret_cast<char*>(&codeSize), sizeof(codeSize)); for (const auto& p : codes) { uint8_t byte = p.first; const std::string& code = p.second; int len = code.size(); out.write(reinterpret_cast<char*>(&byte), 1); out.write(reinterpret_cast<char*>(&len), sizeof(len)); std::bitset<8> bits; for (int i = 0; i < len; ++i) { bits[i % 8] = (code[i] == '1'); if (i % 8 == 7 || i == len - 1) { out.put(static_cast<char>(bits.to_ulong())); bits.reset(); } } } // 核心修复:按块读取+强制刷新进度条 std::ifstream in(inputPath, std::ios::binary); uint8_t buf[BUF_SIZE]; std::string bitStream; while (in.read(reinterpret_cast<char*>(buf), BUF_SIZE)) { size_t bytesRead = in.gcount();//size_t bytesRead = in.gcount(); 是 C++ 输入文件流(std::istream)的 “实际读取字节数获取” 核心代码,用于获取上一次调用 read() 函数时成功读取的字节数 for (size_t i = 0; i < bytesRead; ++i) { bitStream += codes[buf[i]];//构写哈夫曼编码串 } fileCompleted += bytesRead; // 强制更新进度,哪怕只读取1KB ProgressUtils::updateFileProgress(fileName, fileTotal, fileCompleted, "文件压缩"); } // 处理剩余字节 size_t remaining = in.gcount(); if (remaining > 0) { for (size_t i = 0; i < remaining; ++i) { bitStream += codes[buf[i]]; } fileCompleted += remaining; ProgressUtils::updateFileProgress(fileName, fileTotal, fileCompleted, "文件压缩"); } in.close(); // 处理填充位 int pad = 8 - (bitStream.size() % 8); if (pad != 8) { bitStream += std::string(pad, '0'); } out.write(reinterpret_cast<char*>(&pad), sizeof(pad)); for (size_t i = 0; i < bitStream.size(); i += 8) { std::string byteStr = bitStream.substr(i, 8); std::bitset<8> bits(byteStr); out.put(static_cast<char>(bits.to_ulong())); } out.close(); // 确保100%进度显示完整 ProgressUtils::updateFileProgress(fileName, fileTotal, fileTotal, "文件压缩"); std::cout << "单文件压缩完成:" << outputPath << std::endl; return true; } bool decompress(const std::string& inputPath, const std::string& outputPath) override { std::cout << "进入单文件解压路径" << std::endl; if (!FileUtils::pathExists(inputPath)) { std::cerr << "错误:压缩包不存在 " << inputPath << std::endl; return false; } std::ifstream in(inputPath, std::ios::binary); if (!in) { std::cerr << "错误:打开压缩包失败 " << inputPath << std::endl; return false; } int codeSize; if (!in.read(reinterpret_cast<char*>(&codeSize), sizeof(codeSize))) { std::cerr << "错误:压缩包损坏,无法读取编码表大小" << std::endl; in.close(); return false; } std::unordered_map<std::string, uint8_t> codeMap; for (int i = 0; i < codeSize; ++i) { uint8_t byte; int len; if (!in.read(reinterpret_cast<char*>(&byte), 1) || !in.read(reinterpret_cast<char*>(&len), sizeof(len))) { std::cerr << "错误:压缩包损坏,编码表读取失败" << 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 = 0; k < 8 && code.size() < len; ++k) { code += bits[k] ? "1" : "0"; } } codeMap[code] = byte; } int pad; if (!in.read(reinterpret_cast<char*>(&pad), sizeof(pad))) { std::cerr << "错误:压缩包损坏,无法读取填充位" << std::endl; in.close(); return false; } std::string bitStream; uint8_t byte; while (in.read(reinterpret_cast<char*>(&byte), 1)) { bitStream += std::bitset<8>(byte).to_string(); } in.close(); if (pad != 8 && bitStream.size() >= pad) { bitStream = bitStream.substr(0, bitStream.size() - pad); } // 进度配置:按解码字节数更新,强制显示 std::string fileName = FileUtils::getFileName(outputPath); uint64_t fileTotal = bitStream.size() / 8; // 预估大小 uint64_t fileCompleted = 0; const uint32_t BUF_SIZE = 1024; std::cout << "\n开始解压:" << fileName << "(预估大小:" << fileTotal << " B)" << std::endl; std::ofstream out(outputPath, std::ios::binary); if (!out) { std::cerr << "错误:无法创建输出文件 " << outputPath << std::endl; return false; } std::string currentCode; uint8_t writeBuf[BUF_SIZE]; size_t bufIdx = 0; bool isProgressFinalPrinted = false; // 标记是否已打印最终进度 for (char bit : bitStream) { currentCode += bit; if (codeMap.count(currentCode)) { writeBuf[bufIdx++] = codeMap[currentCode]; fileCompleted++; currentCode.clear(); // 缓冲区满或进度完成时写入+更新进度 if (bufIdx == BUF_SIZE || fileCompleted == fileTotal) { out.write(reinterpret_cast<char*>(writeBuf), bufIdx); bufIdx = 0; ProgressUtils::updateFileProgress(fileName, fileTotal, fileCompleted, "文件解压"); // 若进度已100%,标记为已打印,避免后续重复 if (fileCompleted == fileTotal) { isProgressFinalPrinted = true; } } } } // 处理剩余缓冲区数据 if (bufIdx > 0) { out.write(reinterpret_cast<char*>(writeBuf), bufIdx); // 若剩余数据导致进度完成,补充打印进度(避免遗漏) if (!isProgressFinalPrinted && fileCompleted == fileTotal) { ProgressUtils::updateFileProgress(fileName, fileTotal, fileCompleted, "文件解压"); isProgressFinalPrinted = true; } } out.close(); // 仅在未打印最终进度时,才执行修正(避免重复) if (!isProgressFinalPrinted) { ProgressUtils::updateFileProgress(fileName, fileCompleted, fileCompleted, "文件解压"); } std::cout << "单文件解压完成:" << outputPath << std::endl; return true; } };结合此代码,能否给出优化
11-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值