4

私は、ストリームとバイト配列を解凍するだけでなく、それらを圧縮する機能が必要なプロジェクトに取り組んでいます。ストリームから Zip を作成してから解凍する単体テストをいくつか実行していましstreamToZip.Seek(o,SeekOrigin.Begin)streamToZip.Flush()。これを行わないと、「ブロックを読み取れません、データがありません」というエラーが表示されZipFile.Read(stream)ます。

その理由を誰かが説明できるかどうか疑問に思っていました。実際に相対読み取り位置を設定するためにそれを使用することに関するいくつかの記事を見てきましたが、この状況でそれが必要な理由を実際に説明しているものはありません。

ここに私のコードがあります:

オブジェクトの圧縮:

   public Stream ZipObject(Stream data)
    {
        var output = new MemoryStream();
        using (var zip = new ZipFile())
        {
            zip.AddEntry(Name, data);
            zip.Save(output);
            FlushStream(output);
            ZippedItem = output;
        }

        return output;
    }

オブジェクトの解凍:

 public List<Stream> UnZipObject(Stream data)
    {
        ***FlushStream(data); // This is what I had to add in to make it work***

        using (var zip = ZipFile.Read(data))
        {
            foreach (var item in zip)
            {
                var newStream = new MemoryStream();
                item.Extract(newStream);
                UnZippedItems.Add(newStream);
            }
        }
        return UnZippedItems;
    }

私が追加しなければならなかったフラッシュメソッド:

    private static void FlushStream(Stream stream)
    {
        stream.Seek(0, SeekOrigin.Begin);
        stream.Flush();
    }
4

2 に答える 2

8

outputから戻るとZipObject、そのストリームは最後にあり、データを書き込んだところです。データを読み取れるように、「巻き戻す」必要があります。ビデオ カセットを持っていて、番組を録画したばかりだと想像してみてください。見る前に巻き戻す必要がありますよね? ここはまったく同じです。

ただし、これ自体を行うことをお勧めします-呼び出しが必要ZipObjectだとは思いません。Flush私も個人的にこのPositionプロパティを使用します:

public Stream ZipObject(Stream data)
{
    var output = new MemoryStream();
    using (var zip = new ZipFile())
    {
        zip.AddEntry(Name, data);
        zip.Save(output);
    }
    output.Position = 0;
    return output;
}
于 2013-09-26T12:29:20.713 に答える
3

ストリームに書き込むと、位置が変更されます。(同じストリーム オブジェクト) を解凍する場合は、位置をリセットする必要があります。そうしないと、が から始まるEndOfStreamExceptionため、が得られます。ZipFile.Readstream.Position

そう

stream.Seek(0, SeekOrigin.Begin); 

または

stream.Position = 0; 

トリックを行うでしょう。


トピック外ですが、確かに便利です:

public IEnumerable<Stream> UnZipObject(Stream data)
{
    using (var zip = ZipFile.Read(data))
    {
        foreach (var item in zip)
        {
            var newStream = new MemoryStream();
            item.Extract(newStream);
            newStream.Position = 0;
            yield return newStream;
        }
    }
}

メモリ内のすべてのアイテムを解凍しません ( でMemoryStream使用されているためUnZipObject()、反復された場合のみです。これは、抽出されたアイテムが生成されるためです ( を返すIEnumerable<Stream>) 生成に関する詳細情報: http://msdn.microsoft.com/en-us/ライブラリ/vstudio/9k7k7cf0.aspx

通常、ストリームはイテレータのようなものであるため、データをストリームとして返すことはお勧めしません(.Positionを現在の位置として使用します)。このように、デフォルトではスレッドセーフではありません。これらのメモリ ストリームを として返したいと思いますToArray()

于 2013-09-26T12:29:46.227 に答える