2016-10-27 5 views
4

私はzipアーカイブからストリームを集約するために使用する関数を持っています。zip内のジップがドキュメント化されていない状態で開きます。System.IO.Compression.SubReadStream

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を持っている場合は、私がDeflateStreamにストリームをキャストにexcpetionを取得:

System.InvalidCastExceptionの:型のオブジェクトをキャストすることができません「System.IO.Compression.SubReadStream」とタイプします'System.IO.Compression.DeflateStream'。

SubReadStreamのMicrosoftドキュメントが見つかりません。私はジップの中で私のジップをDeflateStreamとしたいと思います。これは可能ですか?もしそうなら、どのように?

UPDATE

まだない成功。私は、次のコードを使用してストリームをコピーするのサンシャインの提案@未遂:

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を得る:ストリームが読み取りをサポートしていません。

私はdeflateStream.CanReadを検査したが、それは真である。

これは、ジップだけでなく、圧縮されていない(たとえば小さすぎるなどの理由で)ジップ内にあるファイルで発生することがわかりました。確かにこれに対処する方法があります。確かに誰かがこれに遭遇しました。私はこの質問の恩恵を受けています。

SubReadStream.NET sourceは@Quanticのおかげです。

+0

「_archive」のタイプは何ですか? – Quantic

+0

'System.IO.Compression.ZipArchive'。ありがとう。 –

+0

.NETコアである必要があります:https://github.com/dotnet/corefx/blob/bffef76f6af208e2042a2f27bc081ee908bb390b/src/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs – Quantic

答えて

3

ZipArchiveEntry.Open()の戻り値の型はStreamです。抽象型で、実際にはDeflateStream(あなたがうれしい)、SubReadStream(boo)、WrappedStream(boo)のいずれかになります。彼らがいつかクラスを改善し、ZopfliStream(ブー)を使用することに決めたら、あなたは悲しいです。回避策は良くありません。圧縮されていないデータ(boo)を収縮しようとしています。

ブーが多すぎます。

のみ解決方法は、OtherFileStreamsメンバーのタイプを変更することです。私たちはそれを見ることができません、List<DeflateStream>のようなにおいがします。それはList<Stream>である必要があります。

+0

'DeflateStream'の代わりに' MemoryStream'を使用して解決しました。プッシュがより高いレベルで解決することに感謝します。 –

1

他のジップの中にジップファイルを保存するときのように、ジップを収縮させるのではなく、ジップの内容を残りのファイルとともにインラインでZIPファイル。既に圧縮されているものに圧縮を適用するのは時間の無駄だから、意味がある。

このzipファイルはアーカイブ内にCompressionMethodValues.Storedとしてマークされています。これにより、.NETはDeflateStreamでラップする代わりに、元のストリームを返します。ここ

出典:https://github.com/dotnet/corefx/blob/master/src/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs#L670

それはDeflateStreamはない場合(あなたが内部のファイルに興味があるなら)あなたは

、ZIPARCHIVEに

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が動作する

関連する問題