简体   繁体   English

从 memory 中的.zip 文件中获取字节数组,无需向磁盘写入任何内容

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

I'm trying to take an existing.zip file (I get it from an api as byte array), take some files from it, and make a new.zip file.我正在尝试获取现有的.zip 文件(我从 api 作为字节数组获取它),从中获取一些文件,然后制作一个新的.zip 文件。 Then return that new.zip file as byte array.然后将 new.zip 文件作为字节数组返回。 The catch is that all of this should be done in memory, without writing any actual files to disk.问题是所有这些都应该在 memory 中完成,而不需要将任何实际文件写入磁盘。

So I have this setup.所以我有这个设置。 First memory stream and ziparchive is used for the orignal zip file.首先 memory stream 和 ziparchive 用于原始 zip 文件。 Second stream and archive represents the second zip that will only contained filtered items from the first 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);

Then I go through each entry and copy contents over to the second zip.然后我通过每个条目 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);
        }

Finally, I need to return that second ziparchive as byte array.最后,我需要将第二个 ziparchive 作为字节数组返回。 I assumed I that I could just call MemoryStream.ToArray(), but the MemoryStream, used by the second ZipArchive, remains empty, despite ZipArchive having files.我以为我可以只调用 MemoryStream.ToArray(),但第二个 ZipArchive 使用的 MemoryStream 仍然是空的,尽管 ZipArchive 有文件。 So how do I get byte[] from ZipArchive?那么如何从 ZipArchive 中获取 byte[] 呢?

I was able to get the following to work with minor tweaks.我能够通过细微的调整获得以下内容。 You appear to be missing the step where you set the position you wish to start reading from: subRepoStream.Seek(0, SeekOrigin.Begin);您似乎缺少设置 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();

The problem is that you are not closing the new ZipArchive before looking at the stream.问题是您在查看 stream 之前没有关闭新的ZipArchive You can do this simply by using the old style using block您可以简单地通过使用旧样式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;

Note that async doesn't make a huge amount of sense when using MemoryStream as it's all sync anyway.请注意, async在使用MemoryStream时没有多大意义,因为无论如何它都是同步的。

It's a shame there is no rename facility on ZipArchiveEntry .遗憾的是ZipArchiveEntry上没有重命名功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#Asp.Net创建文本文件,压缩并保存到Blob - 无需向磁盘写入任何内容 - C# Asp.Net Create text file, zip it, and save to Blob - Without writing anything to disk 将byte []转换为文件流而无需写入磁盘 - Convert byte[] to file stream without writing to disk 如何压缩文件并通过HTTP发送而无需写入磁盘或将完整文件加载到内存中? - How to zip a file and send over HTTP without writing to disk or loading the full file in memory? 如何压缩目录然后返回生成的字节数组,而无需在磁盘上物理创建 zip 文件? - How can I compress a Directory then return the resulting byte array, without physically creating zip file on disk? 在内存中写入文本文件而不存储到磁盘 - Writing a text file in memory without storing to disk 从列表创建Zip文件 <Byte[]> 在记忆中 - Create Zip File from List<Byte[]> in Memory 通过我的服务器将文件从远程服务器复制到客户端浏览器,而无需将整个文件写入磁盘或内存 - Copy file from remote server to client browser via my server without writing the entire file to disk or memory 将 ZIP 文件解压缩到内存(不是磁盘) - Extract ZIP file to memory (not disk) 如何从字节数组创建文件并将其作为文件发送到流中,而无需在磁盘上创建此文件? - How can I create a file from a byte array and send it to the stream as a file without creating this file on the disk? 使用字节数组从内存映射文件获取动态类 - Using a byte array to get a dynamic class from a memory map file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM