Ziparchive解包多部分zip文件
本文关键字:zip 文件 包多部 Ziparchive | 更新日期: 2023-09-27 18:18:02
我希望通过ZipArchive解压缩多部分zip文件。解压缩一个"独立"的zip文件工作,但如果我试图解压缩第一个文件,它只是抛出一个错误。它在windows资源管理器中是这样工作的(只是解压缩第一个文件),所以我猜它可能有效,因为我在网上找不到任何其他方法。
using (ZipArchive archive = new ZipArchive(fs)) {
archive.ExtractToDirectory(tempLocation, true);
}
但是,也许这是一个XY问题,所以我使用它作为块文件下载的简化方式。我们将这个用于updateservice,它下载更新的内容。为了灵活一点,我们将使用(多部分)zip文件。如果这是错误的方法,请告诉我。
编辑:在弄清楚第一个错误是PEBCAK后,我得到了"不支持分裂或传播档案"的错误。
是否有其他Zipfile库支持它?
我建议使用DotNetZip来完成您想要的。
首先,您必须将所有的".zip "文件组合在一起。001 . zip。002 . zip。将003"的文件合并成一个大文件,然后按照正常方式解压:
string destFileName = @"C:'Temp'zip'finalHugeFile.zip";
List<string> myMultiPartZip00xFiles = System.IO.Directory.GetFiles(@"C:'Temp'zip", "*.zip.*").ToList();
using (Stream destStream = File.OpenWrite(destFileName))
{
foreach (string srcFileName in myMultiPartZip00xFiles)
{
using (Stream srcStream = File.OpenRead(srcFileName))
{
srcStream.CopyTo(destStream);
}
}
}
// we extract here
using (ZipFile zip = ZipFile.Read(destFileName))
{
foreach (ZipEntry entry in zip)
{
entry.Extract(@"C:'Temp'zip", ExtractExistingFileAction.OverwriteSilently);
}
}
Multipart zip只是一个普通的zip文件。因此,我们需要一个Stream
,将多个文件合并为一个:
var multiFileStream = new MultiFileStream(new[] { "a.001", "a.002" });
using var zip = new ZipArchive(multiFileStream);
// ...
public class MultiFileStream : Stream
{
private readonly IList<string> _files;
private int _fileIdx;
private FileStream? _file;
public MultiFileStream(IList<string> files)
{
_files = files;
}
public override int Read(byte[] buffer, int offset, int count)
{
while (true)
{
_file ??= File.OpenRead(_files[_fileIdx]);
var res = _file.Read(buffer, offset, count);
if (res > 0)
{
return res;
}
_file.Dispose();
_file = null;
if (_fileIdx < _files.Count - 1)
{
_fileIdx++;
}
else
{
return 0;
}
}
}
public override void Flush() => throw new NotSupportedException();
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => throw new NotSupportedException();
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
}
另一个答案是有效的,但由于临时文件和所有的复制(大档案甚至可能耗尽磁盘空间),速度要慢得多。