Visual Studio C++ 压缩 API 编译并成功压缩单个文件,使用提取向导解压缩文件会在随附的屏幕截图中给出错误:
我是否缺少正确压缩单个文件以便解压缩可以在文件资源管理器中工作的内容?
感谢您的帮助。
Windows 11 Visual Studio C++ 2022 桌面目标 英特尔酷睿 i9
来自 Windows 网站的代码:使用缓冲模式下的压缩 API,并使用代码压缩 jpg (HDMI.jpg),创建名为 Myzip.zip 的压缩文件。输入文件大小为 104269 字节,压缩后大小减少到 100676。
我预计解压缩文件会创建一个名为 HDMI.jpg 的未压缩文件,但我收到了错误 无法完成压缩(zipped)文件夹提取向导压缩(zipped)文件夹为空。在解压文件之前,您必须将文件复制到此压缩文件夹中。
有一个WriteFile函数,看起来成功了。已在调试 (x64) 模式和发布 (x64) 模式下尝试过此操作。在 IDE 或命令提示符中运行最终程序会出现同样的问题。我还尝试在 CreateCompressor 的参数中使用不同的算法,例如 COMPRESS_ALGORITHM_XPRESS_HUFF 和 COMPRESS_ALGORITHM_MSZIP,并且在提取时都出现相同的错误。
尝试了未压缩的jpg文件,也尝试了txt文件,在尝试解压缩时都出现相同的错误。
还尝试了 7-zip,也有同样的错误。
#include <Windows.h>
#include <stdio.h>
#include <compressapi.h>
void wmain(_In_ int argc, _In_ WCHAR* argv[])
{
COMPRESSOR_HANDLE Compressor = NULL;
PBYTE CompressedBuffer = NULL;
PBYTE InputBuffer = NULL;
HANDLE InputFile = INVALID_HANDLE_VALUE;
HANDLE CompressedFile = INVALID_HANDLE_VALUE;
BOOL DeleteTargetFile = TRUE;
BOOL Success;
SIZE_T CompressedDataSize, CompressedBufferSize;
DWORD InputFileSize, ByteRead, ByteWritten;
LARGE_INTEGER FileSize;
ULONGLONG StartTime, EndTime;
double TimeDuration;
if (argc != 3)
{
wprintf(L"Usage:\n\t%s <input_file_name> <compressd_file_name>\n", argv[0]);
return;
}
// Open input file for reading, existing file only.
InputFile = CreateFile(
argv[1], // Input file name
GENERIC_READ, // Open for reading
FILE_SHARE_READ, // Share for read
NULL, // Default security
OPEN_EXISTING, // Existing file only
FILE_ATTRIBUTE_NORMAL, // Normal file
NULL); // No attr. template
if (InputFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Cannot open \t%s\n", argv[1]);
goto done;
}
// Get input file size.
Success = GetFileSizeEx(InputFile, &FileSize);
if ((!Success) || (FileSize.QuadPart > 0xFFFFFFFF))
{
wprintf(L"Cannot get input file size or file is larger than 4GB.\n");
goto done;
}
InputFileSize = FileSize.LowPart;
// Allocate memory for file content.
InputBuffer = (PBYTE)malloc(InputFileSize);
if (!InputBuffer)
{
wprintf(L"Cannot allocate memory for uncompressed buffer.\n");
goto done;
}
// Read input file.
Success = ReadFile(InputFile, InputBuffer, InputFileSize, &ByteRead, NULL);
if ((!Success) || (ByteRead != InputFileSize))
{
wprintf(L"Cannot read from \t%s\n", argv[1]);
goto done;
}
// Open an empty file for writing, if exist, overwrite it.
CompressedFile = CreateFile(
argv[2], // Compressed file name
GENERIC_WRITE | DELETE, // Open for writing; delete if cannot compress
0, // Do not share
NULL, // Default security
CREATE_ALWAYS, // Create a new file; if exist, overwrite it
FILE_ATTRIBUTE_NORMAL, // Normal file
NULL); // No template
if (CompressedFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Cannot create file \t%s\n", argv[2]);
goto done;
}
// Create an XpressHuff compressor.
Success = CreateCompressor(
COMPRESS_ALGORITHM_XPRESS_HUFF, // Compression Algorithm
NULL, // Optional allocation routine
&Compressor); // Handle
if (!Success)
{
wprintf(L"Cannot create a compressor %d.\n", GetLastError());
goto done;
}
// Query compressed buffer size.
Success = Compress(
Compressor, // Compressor Handle
InputBuffer, // Input buffer, Uncompressed data
InputFileSize, // Uncompressed data size
NULL, // Compressed Buffer
0, // Compressed Buffer size
&CompressedBufferSize); // Compressed Data size
// Allocate memory for compressed buffer.
if (!Success)
{
DWORD ErrorCode = GetLastError();
if (ErrorCode != ERROR_INSUFFICIENT_BUFFER)
{
wprintf(L"Cannot compress data: %d.\n", ErrorCode);
goto done;
}
CompressedBuffer = (PBYTE)malloc(CompressedBufferSize);
if (!CompressedBuffer)
{
wprintf(L"Cannot allocate memory for compressed buffer.\n");
goto done;
}
}
StartTime = GetTickCount64();
// Call Compress() again to do real compression and output the compressed
// data to CompressedBuffer.
Success = Compress(
Compressor, // Compressor Handle
InputBuffer, // Input buffer, Uncompressed data
InputFileSize, // Uncompressed data size
CompressedBuffer, // Compressed Buffer
CompressedBufferSize, // Compressed Buffer size
&CompressedDataSize); // Compressed Data size
if (!Success)
{
wprintf(L"Cannot compress data: %d\n", GetLastError());
goto done;
}
EndTime = GetTickCount64();
// Get compression time.
TimeDuration = (EndTime - StartTime) / 1000.0;
// Write compressed data to output file.
Success = WriteFile(
CompressedFile, // File handle
CompressedBuffer, // Start of data to write
CompressedDataSize, // Number of byte to write
&ByteWritten, // Number of byte written
NULL); // No overlapping structure
if ((ByteWritten != CompressedDataSize) || (!Success))
{
wprintf(L"Cannot write compressed data to file: %d.\n", GetLastError());
goto done;
}
wprintf(
L"Input file size: %d; Compressed Size: %d\n",
InputFileSize,
CompressedDataSize);
wprintf(L"Compression Time(Exclude I/O): %.2f seconds\n", TimeDuration);
wprintf(L"File Compressed.\n");
DeleteTargetFile = FALSE;
done:
if (Compressor != NULL)
{
CloseCompressor(Compressor);
}
if (CompressedBuffer)
{
free(CompressedBuffer);
}
if (InputBuffer)
{
free(InputBuffer);
}
if (InputFile != INVALID_HANDLE_VALUE)
{
CloseHandle(InputFile);
}
if (CompressedFile != INVALID_HANDLE_VALUE)
{
// Compression fails, delete the compressed file.
if (DeleteTargetFile)
{
FILE_DISPOSITION_INFO fdi;
fdi.DeleteFile = TRUE; // Marking for deletion
Success = SetFileInformationByHandle(
CompressedFile,
FileDispositionInfo,
&fdi,
sizeof(FILE_DISPOSITION_INFO));
if (!Success) {
wprintf(L"Cannot delete corrupted compressed file.\n");
}
}
CloseHandle(CompressedFile);
}
}
Win32 API 不提供创建 zip 格式文件的方法。
需要使用第三方库或自己创建格式。
也许类似:https://learn.microsoft.com/en-us/dotnet/api/system.io.compression.zipfile?view=net-6.0
要在 .NET Framework 应用程序中使用 ZipFile 类,您必须添加 引用 System.IO.Compression.FileSystem 程序集 项目。
#include<iostream>
#include<string>
using namespace System;
using namespace System::IO;
using namespace System::IO::Compression;
System::String^ StdStringToUTF16(std::string s)
{
cli::array<System::Byte>^ a = gcnew cli::array<System::Byte>(s.length());
int i = s.length();
while (i-- > 0)
{
a[i] = s[i];
}
return System::Text::Encoding::UTF8->GetString(a);
}
int main()
{
std::string startPath = "FolderName";
String^ zipPath = ".\\result1.zip";
String^ extractPath = ".\\extract";
ZipFile::CreateFromDirectory(StdStringToUTF16(startPath), zipPath);
ZipFile::ExtractToDirectory(zipPath, extractPath);
return 0;
}