![](/img/trans.png)
[英]Extracting files nested within a zip file using System.IO.Compression C#
[英]Zip within a zip opens to undocumented System.IO.Compression.SubReadStream
我有一個函數用於聚合來自zip存檔的流。
private void ExtractMiscellaneousFiles()
{
foreach (var miscellaneousFileName in _fileData.MiscellaneousFileNames)
{
var fileEntry = _archive.GetEntry(miscellaneousFileName);
if (fileEntry == null)
{
throw new ZipArchiveMissingFileException("Couldn't find " + miscellaneousFileName);
}
var stream = fileEntry.Open();
OtherFileStreams.Add(miscellaneousFileName, (DeflateStream) stream);
}
}
這在大多數情況下效果很好。 但是,如果我在zip中有一個zip,我DeflateStream
流轉換為DeflateStream
:
System.InvalidCastException:無法將類型為“System.IO.Compression.SubReadStream”的對象強制轉換為“System.IO.Compression.DeflateStream”。
我無法找到SubReadStream
Microsoft文檔。 我希望我的拉鏈內拉鏈作為DeflateStream
。 這可能嗎? 如果是這樣的話?
UPDATE
仍然沒有成功。 我試圖@ Sunshine建議使用以下代碼復制流:
private void ExtractMiscellaneousFiles()
{
_logger.Log("Extracting misc files...");
foreach (var miscellaneousFileName in _fileData.MiscellaneousFileNames)
{
_logger.Log($"Opening misc file stream for {miscellaneousFileName}");
var fileEntry = _archive.GetEntry(miscellaneousFileName);
if (fileEntry == null)
{
throw new ZipArchiveMissingFileException("Couldn't find " + miscellaneousFileName);
}
var openStream = fileEntry.Open();
var deflateStream = openStream;
if (!(deflateStream is DeflateStream))
{
var memoryStream = new MemoryStream();
deflateStream.CopyTo(memoryStream);
memoryStream.Position = 0;
deflateStream = new DeflateStream(memoryStream, CompressionLevel.NoCompression, true);
}
OtherFileStreams.Add(miscellaneousFileName, (DeflateStream)deflateStream);
}
}
但我得到了一個
System.NotSupportedException:Stream不支持讀取。
我檢查了deflateStream.CanRead
,這是真的。
我發現這不僅發生在拉鏈上,而且發生在zip文件中但未壓縮的文件中(例如,因為太小)。 當然有辦法解決這個問題; 肯定有人以前遇到過這個。 我正在打開這個問題的賞金。
這是SubReadStream
的.NET源碼 ,感謝@Quantic。
ZipArchiveEntry.Open()的返回類型是Stream
。 一個抽象類型,在實踐中它可以是DeflateStream(你會很高興),SubReadStream(boo)或WrappedStream(boo)。 如果他們決定某天改進課程並使用ZopfliStream(噓),那么你會有禍了嗎? 解決方法不好,您正試圖收縮未壓縮的數據(boo)。
噓聲太多了。
唯一好的解決方案是更改OtherFileStreams
成員的類型。 我們看不到它,聞起來像List<DeflateStream>
。 它需要是List<Stream>
。
所以看起來當將zip文件存儲在另一個zip中時它不會縮小zip,而只是將zip文件的內容與其余文件一起內聯,並提供一些信息,這些條目是子zip文件的一部分。 這是有道理的,因為將壓縮應用於已經壓縮的東西是浪費時間。
此zip文件在歸檔中標記為CompressionMethodValues.Stored
,這會導致.NET只返回它讀取的原始流,而不是將其包裝在DeflateStream中。
來源: https : //github.com/dotnet/corefx/blob/master/src/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs#L670
你可以將流傳遞給ZipArchive,如果它不是DeflateStream(如果你對里面的文件感興趣的話)
var stream = entry.Open();
if (!(stream is DeflateStream))
{
var subArchive = new ZipArchive(stream);
}
或者您可以將流復制到FileStream(如果要將其保存到磁盤)
var stream = entry.Open();
if (!(stream is DeflateStream))
{
var fs = File.Create(Path.GetTempFileName());
stream.CopyTo(fs);
fs.Close();
}
或者復制到您感興趣的任何流。
注意:這也是.NET 4.6的行為方式
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.