使用Win32 Compression API压缩的文件无法通过解压向导提取
问题根源
微软的Win32 Compression API(如CreateCompressor/Compress系列函数)仅提供原始数据流的压缩/解压缩能力,并不负责生成符合PKZIP标准的归档文件。你直接将压缩后的二进制数据写入后缀为.zip的文件,得到的只是一个压缩后的裸数据块,而非包含文件元信息、目录结构的标准Zip归档,因此解压工具无法识别。
解决方法
要生成标准可解压的Zip文件,需要使用专门处理Zip归档的Windows API,而非底层压缩API:
方案1:使用ZipArchive COM接口(推荐)
这是Windows提供的标准Zip归档操作接口,支持创建、读取、修改Zip文件,自动处理标准Zip格式的元数据:
#include <windows.h> #include <shobjidl.h> #include <iostream> #pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "ole32.lib") int main() { HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hr)) { std::cerr << "CoInitializeEx failed: " << hr << std::endl; return 1; } IZipArchive* pZipArchive = NULL; hr = CoCreateInstance(CLSID_ZipArchive, NULL, CLSCTX_INPROC_SERVER, IID_IZipArchive, (void**)&pZipArchive); if (FAILED(hr)) { std::cerr << "CoCreateInstance failed: " << hr << std::endl; CoUninitialize(); return 1; } // 创建新的Zip文件 hr = pZipArchive->Open(L"output.zip", ZIP_ARCHIVE_OPEN_MODE_CREATE); if (FAILED(hr)) { std::cerr << "Open Zip failed: " << hr << std::endl; pZipArchive->Release(); CoUninitialize(); return 1; } // 向Zip中添加目标文件 hr = pZipArchive->AddFile(L"source_file.jpg", L"source_file.jpg"); if (FAILED(hr)) { std::cerr << "AddFile failed: " << hr << std::endl; pZipArchive->Close(); pZipArchive->Release(); CoUninitialize(); return 1; } // 关闭并保存Zip文件 hr = pZipArchive->Close(); if (FAILED(hr)) { std::cerr << "Close Zip failed: " << hr << std::endl; pZipArchive->Release(); CoUninitialize(); return 1; } pZipArchive->Release(); CoUninitialize(); std::cout << "Zip file created successfully." << std::endl; return 0; }
编译时需确保启用COM支持,链接shlwapi.lib和ole32.lib。
方案2:使用LZCreateArchive旧版接口
这是Windows传统的压缩归档接口,也可生成标准Zip文件:
#include <windows.h> #include <lzexpand.h> #include <iostream> #pragma comment(lib, "lz32.lib") int main() { HANDLE hZip = CreateFile(L"output.zip", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hZip == INVALID_HANDLE_VALUE) { std::cerr << "CreateFile failed: " << GetLastError() << std::endl; return 1; } HANDLE hArchive = LZCreateArchive(hZip, ARCHIVE_TYPE_ZIP, NULL); if (hArchive == INVALID_HANDLE_VALUE) { std::cerr << "LZCreateArchive failed: " << GetLastError() << std::endl; CloseHandle(hZip); return 1; } // 添加文件到归档 ARCHIVECALLBACKDATA callbackData = {0}; callbackData.cbSize = sizeof(ARCHIVECALLBACKDATA); BOOL result = LZAddFileToArchive(hArchive, L"source_file.txt", L"source_file.txt", NULL, &callbackData); if (!result) { std::cerr << "LZAddFileToArchive failed: " << GetLastError() << std::endl; LZCloseArchive(hArchive); CloseHandle(hZip); return 1; } // 关闭归档 result = LZCloseArchive(hArchive); if (!result) { std::cerr << "LZCloseArchive failed: " << GetLastError() << std::endl; CloseHandle(hZip); return 1; } CloseHandle(hZip); std::cout << "Zip file created successfully." << std::endl; return 0; }
额外说明
- 之前用
COMPRESS_ALGORITHM_XPRESS_HUFF等算法得到的文件,本质是压缩后的裸数据,若要解压需用对应的CreateDecompressor函数读取,而非通用Zip解压工具。 - 若坚持使用底层压缩API,需自行实现Zip文件格式的封装(包括文件头、目录结构、校验等),这需要熟悉PKZIP规范,复杂度较高,不推荐。
内容的提问来源于stack exchange,提问作者eugenedakin
相关产品推荐
相关产品推荐

