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