4
votes

The deflate function of zlib accepts a Z_FULL_FLUSH option as its argument, as far as I know, when full flush is performed, a full flush point (0,0,0xFF,0xFF) will be set, subsequent data will be independent from the bytes precedes that point, hence makes the compressed data quasi random accessible. I've read a little bit source of dictzip, it took advantage of this feature to implement its chunk-wise random-accessibility, yet kept the compatibility with gzip. I want to reimplement dictzip compressor/decompressor using CLR provided functionality. The decompressor (random parts reader) is easy, I can just use the DeflateStream to decompress the data chunk by chunk, with no problem, but as for the creation, there is a huge obstacle, the API of DeflateStream is too high-level, it seems all deflate details are hidden, hence unexploitable. I really don't like to include a C shared library in my C# project, it makes the cross-platform deployment very painful, and cancels the benefits of choosing coding in C# in the first place. So, what should I do? Is there any way I can circumvent this obstacle merely using managed code? Does Mono provide a lower-level wrapper for zlib so that I can call deflate with full flush option? Any advice will be appreciated!

--- >8 ---

Thanks to Mark Adler who provided the answer. DotNetZip (specifically Ionic.Zlib.DeflateStream) supports exactly the feature I was asking for. The following example shows how it works:

        Encoding u8 = Encoding.UTF8;
        byte[]  s1 = u8.GetBytes("the quick brown fox "),
                s2 = u8.GetBytes("jumps over the lazy dog!");
        var ms = new MemoryStream(100);
        var deflator = new DeflateStream(ms, CompressionMode.Compress, true);
        deflator.FlushMode = FlushType.Full;
        deflator.Write(s1, 0, s1.Length);
        deflator.Flush();
        var pos = ms.Position;//remember the full flush point
        deflator.Write(s2, 0, s2.Length);
        deflator.Dispose();

        var inflator = new DeflateStream(ms, CompressionMode.Decompress);
        ms.Position = pos;
        byte[] buf = new byte[100];
        inflator.Read(buf, 0, s2.Length);
        Console.WriteLine(u8.GetString(buf));//output: jumps over the lazy dog!
1
" it seems all deflate details are hidden" Exactly. Compare with old Java's Deflate They don't let you choose the deflate strategy, nor the compression level (well, only 3 from 9), nor set a dictionary, nor let you instruct the underlying deflater to flush/reset, nor ask about how many byte its has buffered, etc. Why? Because it was hard to implement? No, that logic is already implemented by zlib internally. It's just because that's the MS way. End of rant.leonbloy

1 Answers

2
votes

Try DotNetZip. SO won't let me post less than 30 characters, even though that is a complete and correct answer, so I added this extraneous sentence.