Какой самый простой способ распаковать ZIP-буфер в C #? - PullRequest
0 голосов
/ 12 октября 2018

Когда я использую zlib в C / C ++, у меня есть простой метод uncompress, который требует только два буфера и больше ничего.Его определение таково:

int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong sourceLen); 
/*
Decompresses the source buffer into the destination buffer.  sourceLen is    the byte length of the source buffer.  Upon entry,
destLen is the total size    of the destination buffer, which must be
large enough to hold the entire    uncompressed data.  (The size of
the uncompressed data must have been saved    previously by the
compressor and transmitted to the decompressor by some    mechanism
outside the scope of this compression library.) Upon exit, destLen   
is the actual size of the uncompressed data.

uncompress returns Z_OK if success, Z_MEM_ERROR if there was not    enough memory, Z_BUF_ERROR if there was not enough room in the output 
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
In    the case where there is not enough room, uncompress() will fill
the output    buffer with the uncompressed data up to that point.
*/

Я хочу знать, есть ли у C # аналогичный способ.Я проверил SharpZipLib FAQ следующим образом, но не совсем понял:

Как сжать / распаковать файлы в памяти?

Использование потока памяти при создании потока Zip!

MemoryStream outputMemStream = new MemoryStream();
using (ZipOutputStream zipOutput = new ZipOutputStream(outputMemStream)) {   
// Use zipOutput stream as normal    
...  

Полученные данные можно получить с помощью методов потока памяти ToArray или GetBuffer.

ToArray - самый чистый и простойправильно использовать со штрафом за дублирование выделенной памяти.GetBuffer возвращает необработанный буфер raw, поэтому вам нужно учитывать истинную длину самостоятельно.

См. Справку библиотеки классов Framework для получения дополнительной информации.

Не могу понять,этот блок кода предназначен для сжатия или распаковки, если outputMemStream измеряет сжатый поток или несжатый поток.Я действительно надеюсь, что есть простой для понимания способ, как в zlib.Большое спасибо, если вы можете мне помочь.

1 Ответ

0 голосов
/ 12 октября 2018

Ознакомьтесь с классом ZipArchive , который, я думаю, имеет функции, необходимые для декомпрессии zip-файлов в памяти.

Предполагается, что у вас есть массив байтов (byte []), которые представляют ZIP-файл в памяти, вы должны создать экземпляр объекта ZipArchive, который будет использоваться для чтения этого массива байтов и интерпретировать их как ZIP-файл, который вы хотите загрузить.Если вы проверите в документации доступные конструкторы класса ZipArchive в документации, вы увидите, что им требуется объект потока, из которого будут считываться данные.Итак, первым шагом будет преобразование массива byte [] в поток, который может быть прочитан конструкторами, и вы можете сделать это, используя объект MemoryStream .

Вот пример того, как перечислить все записи внутри ZIP-архива, представленные в памяти в виде байтового массива:

byte [] zipArchiveBytes = ...;   // Read the ZIP file in memory as an array of bytes

using (var inputStream = new MemoryStream(fileBytes))
using (var zipArchive = new ZipArchive(inputStream, ZipArchiveMode.Read))
{
    Console.WriteLine("Listing archive entries...");
    foreach (var archiveEntry in zipArchive.Entries)
        Console.WriteLine($"   {archiveEntry.FullName}");
}

Каждый файл в ZIP-архиве будет представлен как ZipArchiveEntry экземпляр.Этот класс предлагает свойства, которые позволяют вам получать информацию, такую ​​как исходная длина файла из архива ZIP, его сжатая длина, его имя и т. Д.

Для того, чтобы прочитать конкретный файл, который содержится внутриZIP-файл, вы можете использовать ZipArchiveEntry.Open () .Следующий пример иллюстрирует, как открыть определенный файл из архива, если у вас есть FullName внутри ZIP-архива:

ZipArchiveEntry archEntry = zipArchive.GetEntry("my-folder-inside-zip/dog-picture.jpg");
byte[] readResult;
using (Stream entryReadStream = archEntry.Open())
{
    using (var tempMemStream = new MemoryStream())
    {
        entryReadStream.CopyTo(tempMemStream);
        readResult = tempMemStream.ToArray();
    }
}

В этом примере считывается заданное содержимое файла и возвращается какмассив байтов (хранится в переменной byte[] readResult), который затем можно использовать в соответствии с вашими потребностями.

...