(.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;
}

[PR]
by jehoshaphat | 2009-03-21 18:06 | .Net開発 | Trackback | Comments(0)
トラックバックURL : http://jehupc.exblog.jp/tb/9882986
トラックバックする(会員専用) [ヘルプ]
※このブログはトラックバック承認制を適用しています。 ブログの持ち主が承認するまでトラックバックは表示されません。


<< (.Net,SQL)JET(M... (VisualStudio)V... >>