[英]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.