6

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

4

1 回答 1

2

不确定我是否完全理解您的需求(例如,您不需要磁盘上的解压缩文件吗?)。

我正在查看LZMA SDK 9.20及其lzma.txt自述文件,并且有很多提示可以解压缩到内存 - 您可能只需要使用 C API 而不是 C++ 接口。例如,查看名为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;
}
于 2012-08-24T16:17:39.217 回答