C++ Win32 压缩 API 无法使用提取向导进行提取

问题描述 投票:0回答:1

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);
    }
}
c++ visual-studio zip compression unzip
1个回答
0
投票

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 程序集 项目。

在 C++CLR 中使用 .NET API。

#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;
}
© www.soinside.com 2019 - 2024. All rights reserved.