はじめに
一般的な圧縮ストリームは、Close() メソッドか呼ばれるまでバッファリングしてしまって、リアルタイムな相互通信が必要な場合などには使えない。
zebedee などの通信を圧縮してくれるようなツールの互換プログラムは作りにくいだろう。
Javaの場合、SYNC_FLUSHモードが JDK7 から提供されているので、それを使えばいいが、.NET Framework の GZipStreamなどには提供されていない。
しかし、zlib.NET.dll にはSYNC_FLUSHモードが実装されてるので、それを使えばいいと思う。
バージョン
基本的に ver1.04 の話。
使い方(基本)
zlib.NET の demo フォルダを見ればわかると思うけど、一応メモ
zlib.ZOutputStream クラスも zlib.ZInputStream クラスもペースとなるストリームだけの一引数のコンストラクタの場合は、解凍
ペースとなるストリームと、圧縮レベルの二引数のコンストラクタの場合は、圧縮
後は、zlib.ZOutputStream#FlushMode に zlib.zlibConst.Z_SYNC_FLUSH を指定するだけ。
使い方(zlib.ZInputStream の落とし穴)
これ、なぜかSystem.IO.BinaryReader クラスを継承している。
にもかかわらず、BinaryReader クラスの各種メソッドは実装していない!!(ソースコードを見るとわかる)
唯一の実装が Read() と なぜか小文字始まりの read(byte[] b, int off, int len) だ。
まぁ、zlib.ZInputStream クラスをStreamとして包むラッパークラスを自作して、それの Read() を read() に繋げればいいだけの話なんだけど、私は BinaryReader として(BinaryReader.ReadByte()を)そのまま使っていて "解凍しねーな" と数日悩んだので、メモとして残しておくよ。
つまり、zlib.ZInputStream はBinaryReader を継承しているけど、Reader としては不十分なので、各自 Stream のラッパとして包み込んであげてから 再度Reader に包み込んであげればいいと思う。
BouncyCastle/C# でもできた
BouncyCastle/C# でもできた。
BouncyCastle/C# の Org.BouncyCastle.Utilities.Zlib.ZOutputStreamクラス/Org.BouncyCastle.Utilities.Zlib.ZInputStreamクラスの FlushMode プロパティがそれ。
このプロパティに Org.BouncyCastle.Utilities.Zlib.JZlib の Static 値を与えればいいと思う。
Org.BouncyCastle.Utilities.Zlib.JZlib.Z_SYNC_FLUSH とかを与えればいいと思う。
Javaでの捕捉
上の方に「Javaの場合、SYNC_FLUSHモードが JDK7 から提供されているので」と書いているが、Javaの場合は、
DeflaterOutputStream などだけではなく、java.util.zip.GZIPOutputStream にも、Sync_Flush (同期的圧縮)が付いている。(コンストラクタの第二引数に注目)