簡體   English   中英

zip中的Zip打開到未記錄的System.IO.Compression.SubReadStream

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

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