簡體   English   中英

從 memory 中的.zip 文件中獲取字節數組,無需向磁盤寫入任何內容

[英]Get byte array from .zip file in memory, without writing anything to disk

我正在嘗試獲取現有的.zip 文件(我從 api 作為字節數組獲取它),從中獲取一些文件,然后制作一個新的.zip 文件。 然后將 new.zip 文件作為字節數組返回。 問題是所有這些都應該在 memory 中完成,而不需要將任何實際文件寫入磁盤。

所以我有這個設置。 首先 memory stream 和 ziparchive 用於原始 zip 文件。 第二個 stream 和存檔表示第二個 zip,它將僅包含來自第一個 zip 的過濾項目。

        using var downloadedRepoStream = new MemoryStream(binaryRepo);
        using var downloadedRepoArchive = new ZipArchive(downloadedRepoStream, ZipArchiveMode.Read, true);

        var entriesToExtract = downloadedRepoArchive.Entries; //add some filtering

        using var subRepoStream = new MemoryStream();
        using var subRepoArchive = new ZipArchive(subRepoStream, ZipArchiveMode.Create, true);

然后我通過每個條目 go 並將內容復制到第二個 zip。

        foreach (var entry in entriesToExtract)
        {
            var entryName = entry.FullName.Split('/', 2)[1];
            using var entryStream = entry.Open();

            var subRepoEntry = subRepoArchive.CreateEntry(entry.FullName);
            using var subRepoEntryStream = subRepoEntry.Open();

            await entryStream.CopyToAsync(subRepoEntryStream);
        }

最后,我需要將第二個 ziparchive 作為字節數組返回。 我以為我可以只調用 MemoryStream.ToArray(),但第二個 ZipArchive 使用的 MemoryStream 仍然是空的,盡管 ZipArchive 有文件。 那么如何從 ZipArchive 中獲取 byte[] 呢?

我能夠通過細微的調整獲得以下內容。 您似乎缺少設置 position 您希望從中開始閱讀的步驟:subRepoStream.Seek(0, SeekOrigin.Begin);

byte[] binaryRepo = ...
using MemoryStream downloadedRepoStream = new MemoryStream(binaryRepo);
using ZipArchive downloadedRepoArchive = new ZipArchive(downloadedRepoStream, ZipArchiveMode.Read, false);

ReadOnlyCollection<ZipArchiveEntry> entriesToExtract = downloadedRepoArchive.Entries; //add some filtering

using MemoryStream subRepoStream = new MemoryStream();
using ZipArchive subRepoArchive = new ZipArchive(subRepoStream, ZipArchiveMode.Create, false);

foreach (ZipArchiveEntry entry in entriesToExtract)
{
    using Stream entryStream = entry.Open();
    
    ZipArchiveEntry subRepoEntry = subRepoArchive.CreateEntry(entry.FullName);
    using Stream subRepoEntryStream = subRepoEntry.Open();
    
    await entryStream.CopyToAsync(subRepoEntryStream);
}

// before reading the stream you need to set the position to the beginning.
subRepoStream.Seek(0, SeekOrigin.Begin);

byte[] data = subRepoStream.ToArray();

問題是您在查看 stream 之前沒有關閉新的ZipArchive 您可以簡單地通過使用舊樣式using block 來做到這一點

using var downloadedRepoStream = new MemoryStream(binaryRepo);
using var downloadedRepoArchive = new ZipArchive(downloadedRepoStream, ZipArchiveMode.Read, true);

var entriesToExtract = downloadedRepoArchive.Entries; //add some filtering

using var subRepoStream = new MemoryStream();

using (var subRepoArchive = new ZipArchive(subRepoStream, ZipArchiveMode.Create, true))
{
    foreach (var entry in entriesToExtract)
    {
        var entryName = entry.FullName.Split('/', 2)[1];
        using var entryStream = entry.Open();

        var subRepoEntry = subRepoArchive.CreateEntry(entry.FullName);
        using var subRepoEntryStream = subRepoEntry.Open();

        await entryStream.CopyToAsync(subRepoEntryStream);
    }
}

subRepoStream.Position = 0;

請注意, async在使用MemoryStream時沒有多大意義,因為無論如何它都是同步的。

遺憾的是ZipArchiveEntry上沒有重命名功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM