3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(.Net)MemoryStreamのデータをGZipStreamで圧縮するときの注意点...

MDBにデータを格納するときに、圧縮して格納しようと思い、GZipStream で圧縮をかけたのですが、その時にハマったことです。

(MDBで圧縮したデータを保存する列はバイナリ型にしてます。また、DBに圧縮したデータを入れる方法は、ITpro .NETの関数を使用してSQL Server 2005にデータを圧縮格納を参考にしてます。)

とりあえず、.Netについてる GZipStream での圧縮と解凍の方法が、@IT GZIP形式でファイルを圧縮/解凍するには?に載ってたので、これを参考にして下記のようなコードにしました。

上記@ITの例ではファイルに対しての圧縮解凍操作ですが、今回はDBに入れるデータに対してなので、FileStream の代わりに MemoryStream を使ってます。(最近 C# 本格的に始めました。ということで、コードも C# です。)

//圧縮を行う

private Byte[] CompressBytes(Byte[] bytUnComp)

{

int num;

byte[] buf = new byte[1024]; // 1Kbytesずつ処理する

// 入力ストリーム

MemoryStream inStream = new MemoryStream(bytUnComp);

// 出力ストリーム

MemoryStream outStream = new MemoryStream();

// 圧縮ストリーム

GZipStream compStream = new GZipStream(outStream, CompressionMode.Compress);

 

while ((num = inStream.Read(buf, 0, buf.Length)) > 0)

{

compStream.Write(buf, 0, num);

}

return outStream.ToArray();

}

 

//解凍を行う

public static Byte[] UnCompressBytes(byte[] bytComp)

{

int num;

byte[] buf = new byte[1024]; // 1Kbytesずつ処理する

// 入力ストリーム

MemoryStream inStream = new MemoryStream(bytComp);

// 解凍ストリーム

GZipStream decompStream = new GZipStream(inStream, CompressionMode.Decompress);

// 出力ストリーム

MemoryStream outStream = new MemoryStream();

 

while ((num = decompStream.Read(buf, 0, buf.Length)) > 0)

{

outStream.Write(buf, 0, num);

}

return outStream.ToArray();

}

このメソッドを使って、少ないデータ(数バイト)で、圧縮をかけて解凍しようとすると、解凍が正常にできませんでした。

num = decompStream.Read(buf, 0, buf.Length) のところで num = 0 となってしまい、 outStream.Write() が走らないのです。

いろいろ調べてみると、ここここに解決法が載ってました。

どうやら、圧縮時に、outStream.ToArray() を動かす前に、GZipStream が close されてないといけないようです。

ということで、下記のように書き直したらうまくいきました。

//圧縮を行う

private Byte[] CompressBytes(Byte[] bytUnComp)

{

int num;

byte[] buf = new byte[1024]; // 1Kbytesずつ処理する

// 入力ストリーム

MemoryStream inStream = new MemoryStream(bytUnComp);

// 出力ストリーム

MemoryStream outStream = new MemoryStream();

// 圧縮ストリーム

GZipStream compStream = new GZipStream(outStream, CompressionMode.Compress);

 

while ((num = inStream.Read(buf, 0, buf.Length)) > 0)

{

compStream.Write(buf, 0, num);

}

compStream.Close();

byte[] output = outStream.ToArray();

inStream.Close();

outStream.Close();

 

return output;

}

 

//解凍を行う

public static Byte[] UnCompressBytes(byte[] bytComp)

{

int num;

byte[] buf = new byte[1024]; // 1Kbytesずつ処理する

// 入力ストリーム

MemoryStream inStream = new MemoryStream(bytComp);

// 解凍ストリーム

GZipStream decompStream = new GZipStream(inStream, CompressionMode.Decompress);

// 出力ストリーム

MemoryStream outStream = new MemoryStream();

 

while ((num = decompStream.Read(buf, 0, buf.Length)) > 0)

{

outStream.Write(buf, 0, num);

}

 

byte[] output = outStream.ToArray();

inStream.Close();

outStream.Close();

 

return output;

}