0

I am trying to port the following java code to .net:

private final byte[] zipLicense(byte lic[])
{
    byte buf[];
    ByteArrayInputStream bis;
    DeflaterInputStream dis;
    ByteArrayOutputStream bos;
    buf = new byte[64];
    bis = new ByteArrayInputStream(lic);
    dis = new DeflaterInputStream(bis, new Deflater());
    bos = new ByteArrayOutputStream();
    byte abyte0[];
    int len;
    while((len = dis.read(buf)) > 0) 
        bos.write(buf, 0, len);
    abyte0 = bos.toByteArray();
    try
    {
        bis.close();
        dis.close();
        bos.close();
    }
    catch(IOException ex)
    {
        ex.printStackTrace();
    }
    return abyte0;
}

My best shot was this code in C#:

private byte[] zipLicense(byte[] lic)
{
    var outputMemStream = new MemoryStream();

    ZipOutputStream zipStream;

    using (zipStream = new ZipOutputStream(outputMemStream))
    {
        zipStream.Write(lic, 0, lic.Length);
        Debug.WriteLine(string.Format("Compressed bytes: {0}", outputMemStream.Length));
    }

    return outputMemStream.ToArray();
}

ZipOutputStream is a class from SharpZipLib

When I try to run the C# code, I get error on first attempt to write to zipStream

zipStream.Write(lic, 0, lic.Length);

The error states that I haven't provided "No entry". I see in examples that one can and probably should seciffy an entry string to a zip stream, but what java code puts as an entry then? Please help in porting this java functionality to .Net. Thanks!

Maxim V. Pavlov
  • 10,303
  • 17
  • 74
  • 174

1 Answers1

3

The Java DeflaterInputStream is more like .NET's DeflateStream. That is, it's simply a compressed stream, without the directory index that a full .zip file would contain.

Try this:

private byte[] zipLicense(byte[] lic)
{
    var outputMemStream = new MemoryStream();

    using (DeflateStream stream =
        new DeflateStream(outputMemStream, CompressionMode.Compress, true))
    {
        stream.Write(lic, 0, lic.Length);
    }

    Debug.WriteLine(string.Format("Compressed bytes: {0}", outputMemStream.Length));

    return outputMemStream.ToArray();
}

Note that I've added a call to Flush(). Without this, the outputMemStream.Length property may not be current (i.e. not quite the full length of the resulting stream).

For what it's worth, .NET now has reasonably good .zip file support built-in (e.g. ZipArchive class). So if you do find yourself actually needing that some day, I would try to use that first rather than adding a third-party library to your deployment.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thank you for an elegant and native solution. Didn't find DefalteStream class when was looking for a C# alternative. – Maxim V. Pavlov Nov 18 '14 at 21:36
  • I double-checked, and realized that `Flush()` is a NOP here. Instead, you need to make sure `DeflateStream` doesn't dispose the underlying `MemoryStream`, and check the length after the `DeflateStream` is disposed. I've updated the code example to fix that issue. – Peter Duniho Nov 18 '14 at 21:47