我正在开发一个应用程序,它将需要处理不同类型的文件。尽可能多的存档类型是好的。我选择了7zip.dll作为存档 worker 的引擎。但是有一个问题,有人知道如何将文件从存档解压缩到内存缓冲区吗?如我所见,7zip.dll仅支持解压缩到硬盘。另外,从内存缓冲区加载存档也将是一件好事。有没有人尝试做类似的事情?

最佳答案

不知道我是否完全了解您的需求(例如,您是否不需要磁盘上的解压缩文件?)。

我正在查看 LZMA SDK 9.20 及其 lzma.txt 自述文件,并且有很多暗示可以对内存进行解压缩-您可能只需要使用C API而不是C++接口(interface)。例如, check out 名为Single-call Decompressing的部分:

When to use: RAM->RAM decompressing
Compile files: LzmaDec.h + LzmaDec.c + Types.h
Compile defines: no defines
Memory Requirements:
  - Input buffer: compressed size
  - Output buffer: uncompressed size
  - LZMA Internal Structures: state_size (16 KB for default settings)

此外,还有此功能:
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);

您可以通过将归档文件进行内存映射来利用它们。据我所知,如果您的进程创建了一个具有独占访问权限的内存映射文件(因此没有其他进程可以访问它)并且不进行显式刷新,则对该文件的所有更改都将保留在内存中,直到映射被破坏或文件已关闭。或者,您可以只将存档内容加载到内存中。

为了完整起见,我将几个示例汇总为一个在Windows中使用内存映射的演示。
#include <stdio.h>
#include <time.h>
#include <Windows.h>
#include <WinNT.h>

// This demo will limit the file to 4KiB
#define FILE_SIZE_MAX_LOWER_DW 4096
#define FILE_SIZE_MAX_UPPER_DW 0
#define MAP_OFFSET_LOWER_DW 0
#define MAP_OFFSET_UPPER_DW 0
#define TEST_ITERATIONS 1000
#define INT16_SIZE 2

typedef short int int16;

// NOTE: This will not work for Windows less than XP or 2003 Server!
int main()
{
    HANDLE  hFile, hFileMapping;
    PBYTE mapViewStartAddress;
    // Note: with no explicit security attributes, the process needs to have
    // the necessary rights (e.g. read, write) to this location.
    LPCSTR path = "C:\\Users\\mcmlxxxvi\\Desktop\\test.dat";

    // First, open a file handle.
    hFile = CreateFile(path,
                       GENERIC_READ | GENERIC_WRITE,    // The file is created with Read/Write permissions
                       FILE_SHARE_READ,                 // Set this to 0 for exclusive access
                       NULL,                            // Optional security attributes
                       CREATE_ALWAYS,                   // File is created if not found, overwritten otherwise
                       FILE_ATTRIBUTE_TEMPORARY,        // This affects the caching behaviour
                       0);                              // Attributes template, can be left NULL
    if ((hFile) == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "Unable to open file");
        return 1;
    }

    // Then, create a memory mapping for the opened file.
    hFileMapping = CreateFileMapping(hFile,                     // Handle for an opened file
                                     NULL,                      // Optional security attributes
                                     PAGE_READWRITE,            // File can be mapped for Read/Write access
                                     FILE_SIZE_MAX_UPPER_DW,    // Maximum file size split in DWORDs.
                                     FILE_SIZE_MAX_LOWER_DW,    // NOTE: I may have these two mixed up!
                                     NULL);                     // Optional name
    if (hFileMapping == 0)
    {
        CloseHandle(hFile);
        fprintf(stderr, "Unable to open file for mapping.");
        return 1;
    }

    // Next, map a view (a continuous portion of the file) to a memory region
    // The view must start and end at an offset that is a multiple of
    // the allocation granularity (roughly speaking, the machine page size).
    mapViewStartAddress = (PBYTE)MapViewOfFile(hFileMapping,                    // Handle to a memory-mapped file
                                               FILE_MAP_READ | FILE_MAP_WRITE,  // Maps the view for Read/Write access
                                               MAP_OFFSET_UPPER_DW,             // Offset in the file from which
                                               MAP_OFFSET_LOWER_DW,             // the view starts, split in DWORDs.
                                               FILE_SIZE_MAX_LOWER_DW);         // Size of the view (here, entire file)
    if (mapViewStartAddress == 0)
    {
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        fprintf(stderr, "Couldn't map a view of the file.");
        return 1;
    }

    // This is where actual business stuff belongs.
    // This example application does iterations of reading and writing
    // random numbers for the entire length of the file.

    int16 value;
    errno_t result = 0;

    srand((int)time(NULL));
    for (int i = 0; i < TEST_ITERATIONS; i++)
    {
        // Write
        for (int j = 0; j < FILE_SIZE_MAX_LOWER_DW / INT16_SIZE; j++)
        {
            value = rand();
            result = memcpy_s(mapViewStartAddress + j * INT16_SIZE, INT16_SIZE, &value, INT16_SIZE);
            if (result != 0)
            {
                CloseHandle(hFileMapping);
                CloseHandle(hFile);
                fprintf(stderr, "File write error during iteration #%d, error %d", i, GetLastError());
                return 1;
            }
        }
        // Read
        SetFilePointer(hFileMapping, 0, 0, FILE_BEGIN);
        for (int j = 0; j < FILE_SIZE_MAX_LOWER_DW / sizeof(int); j++)
        {
            result = memcpy_s(&value, INT16_SIZE, mapViewStartAddress + j * INT16_SIZE, INT16_SIZE);
            if (result != 0)
            {
                CloseHandle(hFileMapping);
                CloseHandle(hFile);
                fprintf(stderr, "File read error during iteration #%d, error %d", i, GetLastError());
                return 1;
            }
        }
    }

    // End business stuff

    CloseHandle(hFileMapping);
    CloseHandle(hFile);

    return 0;
}

关于使用7zip.dll的C++,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12040399/

10-10 23:58