DOBON.NET DOBON.NETプログラミング掲示板過去ログ

GZipStreamを使った圧縮・解凍について

環境/言語:[WindowsXP、VB2005]
分類:[.NET]

はじめまして。
GZipStreamとMemoryStreamを使い、ファイルではなく
メモリ内で圧縮と解凍を行っているのですが解凍がなぜかできません。
サンプルのソースは以下のようになってます。
単純に、一度Byte配列を圧縮し、圧縮後のByte配列を再度解凍しています。
(しようとしています。。。)
ここで、下から3行目のReadで、戻り値も0で圧縮解除後のデータが
取得できないのはなぜでしょう?
汚いソースで恐縮ですが、よろしくご教示ください。

Dim orgData(0 To 9) As Byte '元データのByte配列
Dim i As Byte

'元データの設定
For i = 0 To 9
orgData(i) = i
Next

'圧縮
Dim comp() As Byte '圧縮後のByte配列
Dim CompMemStream As New System.IO.MemoryStream()
Dim CompGzipStream As New Compression.GZipStream _
(CompMemStream, CompressionMode.Compress)

CompGzipStream.Write(orgData, 0, orgData.Length) ’圧縮

comp = CompMemStream.ToArray() '圧縮後のByte配列をMemoryStreamから取得

CompGzipStream.Close()
CompMemStream.Close()

'解凍
Dim decomp(0 To 9) As Byte '解凍後のByte配列
Dim DeCompStream As New MemoryStream(comp) '圧縮されたByte配列からMemoryStreamを生成
Dim DeCompGzipStream As New Compression.GZipStream _
(DeCompStream, CompressionMode.Decompress)

Dim ret As Integer
ret = DeCompGzipStream.Read(decomp, 0, 10) 'ここで圧縮解除後のデータが取得できない

DeCompGzipStream.Close()
DeCompStream.Close()
2006/06/08(Thu) 11:07:59 編集(投稿者)

※良く見れば、目が節穴になっていました(orz
 混乱を招くだけの様に思いましたので、投稿を削除しました
GZipStream はバッファリングを行うので、書き込み途中ではまともに書き込んでいません。
圧縮する際、GZipStream を Close してから ToArray を呼び出して下さい。
■No16153に返信(Hongliangさんの記事)
> GZipStream はバッファリングを行うので、書き込み途中ではまともに書き込んでいません。
> 圧縮する際、GZipStream を Close してから ToArray を呼び出して下さい。

おぉ・・・そういうことでしたか。
確かに、先にCloseした場合と元の例のソースの場合では
圧縮後の配列(例のcomp)のlengthが異なっていました。

そして解凍後の配列も取得できました!
ありがとうございました!!
解決済み!
>Hongliangさん
書き込み途中で読み込んで、でしょうか。

それと補足。
MSDN にも書いてありますが、GZipStream を Close すると基になっている MemoryStream
も閉じてしまいます。
その状態で ToArray しても読み込めません(たぶん)。
GZipStream を New するときに、第3引数に true を追加してあげてください。

と思って書いてきたら、すでに解決していた ○| ̄|_
解決済み!
■No16157に返信(ぽぴ王子さんの記事)
> >Hongliangさん
> 書き込み途中で読み込んで、でしょうか。

おっしゃるとおり、どうやら書き込み途中の内容しか取得できていなかったようです。

> それと補足。
> MSDN にも書いてありますが、GZipStream を Close すると基になっている MemoryStream
> も閉じてしまいます。
> その状態で ToArray しても読み込めません(たぶん)。
> GZipStream を New するときに、第3引数に true を追加してあげてください。

試しに、第3引数をfalseにしてみましたが、一応ToArrayできてるようです。
ただ、やはり念のためTrueにしておきます。
ご指摘ありがとうございました。

> と思って書いてきたら、すでに解決していた ○| ̄|_
いえいえ、参考になりました〜ありがとう!
解決済み!
> MSDN にも書いてありますが、GZipStream を Close すると基になっている MemoryStream
> も閉じてしまいます。
> その状態で ToArray しても読み込めません(たぶん)。


> MemoryStream.ToArray メソッド
> メモ
> このメソッドは、MemoryStream が閉じられているときに機能します。

むしろ、閉じてない時に ToArray が働くとはどこにも書いてないんですよね……(英語版でも)。
一応今まで問題はなかったですが。
■No16159に返信(Hongliangさんの記事)
>>MSDN にも書いてありますが、GZipStream を Close すると基になっている MemoryStream
>>も閉じてしまいます。
>>その状態で ToArray しても読み込めません(たぶん)。
>
>
>>MemoryStream.ToArray メソッド
>>メモ
>>このメソッドは、MemoryStream が閉じられているときに機能します。
>
> むしろ、閉じてない時に ToArray が働くとはどこにも書いてないんですよね……(英語版でも)。
> 一応今まで問題はなかったですが。

む。確かにヘルプには閉じられているときに・・・との記述がありますね。
確かに先にMemoryStreamを閉じてもできました。むしろこっちが正しい??
どちらでもToArrayできそうですが、基本的にはMemoryStreamが
閉じられている時にToArrayするのが正しいのでしょうね。
そのように修正しておくことにします。
解決済み!
>MemoryStream.ToArray メソッド
>メモ
>このメソッドは、MemoryStream が閉じられているときに機能します。

あらやだ!ホントね奥さん(いや、誰が奥さんなのか…)
もうすっかり「開いているときしか動かない」と固定観念で見てました。

全然関係ないですが、GZipStream って圧縮させるときに元データよりも大きくなること
が多々ありますよね?(今回も10バイトが120バイトぐらいになっててびびった)
アレって仕方がないことなんでしょうか。
気になってるなら別スレ立てるべきなのかもしれませんが、とりあえず雑談レベルという
ことで。あ、雑談はお気楽掲示板行き?
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板