在c#中使用zlib.net压缩和解压缩字符串

问题描述 投票:0回答:3

我在c#中使用zlib.net来压缩和解压缩字符串。

这是我的代码

class GZOutputStream : ZOutputStream
{
    public GZOutputStream(Stream in_Renamed) : base(in_Renamed)
    {
        byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
        z.inflateSetDictionary(dictionary, dictionary.Length);
    }

    public GZOutputStream(Stream in_Renamed, int level) : base(in_Renamed, level)
    {
        byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(sDictionary);
        z.deflateSetDictionary(dictionary, dictionary.Length);
    }
}

public static byte[] compressString(string source)
{ 
    byte[] buffer = System.Text.Encoding.Default.GetBytes (source);

    MemoryStream memOutput = new MemoryStream ();
    GZOutputStream zipOut   = new GZOutputStream(memOutput, zlibConst.Z_DEFAULT_COMPRESSION);

    zipOut.Write(buffer, 0, buffer.Length);
    zipOut.finish();

    memOutput.Seek(0, SeekOrigin.Begin);
    byte[] result = memOutput.ToArray();

    return result;
}

public static byte[] deCompressString(string source)
{ 
    byte[] buffer = System.Text.Encoding.Default.GetBytes (source);
    MemoryStream memOutput = new MemoryStream ();
    GZOutputStream zipOut   = new GZOutputStream(memOutput);

    zipOut.Write(buffer, 0, buffer.Length);
    zipOut.finish();

    memOutput.Seek(0, SeekOrigin.Begin);
    byte[] result = memOutput.ToArray();

    return result;
}

当我压缩字符串时,效果很好。但是,当我解压缩 compress 函数的结果字符串时,出现异常:

ZStreamException:膨胀:
zlib.ZOutputStream.Write (System.Byte[] b1, Int32 off, Int32 len)

那么解决办法是什么呢?

c# zlib
3个回答
0
投票
    public static string DeCompressToString(byte[] buffer)
    {
        MemoryStream memOutput = new MemoryStream();
        ZOutputStream zipOut = new ZOutputStream(memOutput);

        zipOut.Write(buffer, 0, buffer.Length);
        zipOut.finish();

        memOutput.Seek(0, SeekOrigin.Begin);
        byte[] result = memOutput.ToArray();

        var str = System.Text.Encoding.Default.GetString(result);

        return str;
    }

0
投票

5年前的问题,我知道,但对于仍在寻找的人(我也是),问题是 ZOutputStream 中的 Write 方法在第一次调用 z.inflate 后返回 zlibConst.Z_NEED_DICT ,这就是字典的时间需要提供。 因此,您需要重写 Write 方法,测试该返回并在此时提供字典...

public override void Write(System.Byte[] b1, int off, int len)
    {
        if (len == 0)
            return;
        int err;
        
        z.next_in = b1;
        z.next_in_index = off;
        z.avail_in = len;
        do
        {
            z.next_out = buf;
            z.next_out_index = 0;
            z.avail_out = bufsize;
            if (compress)
                err = z.deflate(flush_Renamed_Field);
            else
                err = z.inflate(flush_Renamed_Field);

            if (err == zlibConst.Z_NEED_DICT)
            {
                int y=z.inflateSetDictionary(dict, dict.Length);
                err = z.inflate(flush_Renamed_Field);
            }

            if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END)
            {
                throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
            }
            ms.Write(buf, 0, bufsize - z.avail_out);
        }
        while (z.avail_in > 0 || z.avail_out == 0);
    }
   
}

0
投票

今天偶然发现了同样的错误消息。在生产代码中使用 zlib.net 超过 15 年之后。 对于特定的二进制文件,我可以压缩它,但是在解压缩它时,一些看似随机的文件,它无法解压缩,我们总是得到

ZStreamException: inflating:
错误。

在查看了 Glen 的上述答案后,我测试了

Write(byte[], int, int)
方法重写,发现
z.inflate
在 800 个块中的大约 700 个块之后返回 -5 (Z_BUF_ERROR)。 zlib 手册 声明如下:

如果没有进展,则

inflate() 返回 [...] Z_BUF_ERROR 或 如果 Z_FINISH 时输出缓冲区没有足够的空间 用过的。请注意,Z_BUF_ERROR不是致命的,并且 inflate() 可以是 再次调用更多输入和更多输出空间以继续 减压。

deflate()
功能基本相同。据此,可能会出现返回 Z_BUF_ERROR 的情况,在这种情况下,(解)压缩可以继续而不是抛出异常。我们现在使用的派生类是这样的:

/// <summary>
/// ZOutputStream which fixes issues in zlib.net 1.0.4
/// </summary>
internal class MyOutputStream : zlib.ZOutputStream
{
    private Stream m_outStream;

    public MyOutputStream(Stream outStream) : base(outStream)
    {
        m_outStream = outStream;
    }
    
    public MyOutputStream(Stream outStream, int level) : base(outStream, level)
    {
        m_outStream = out_Renamed;
    }
    
    public override void Write(byte[] buffer, int offset, int length)
    {
        if (length == 0)
            return;

        int err;
        z.next_in = buffer;
        z.next_in_index = offset;
        z.avail_in = length;
        do
        {
            z.next_out = buf;
            z.next_out_index = 0;
            z.avail_out = bufsize;

            if (compress)
                err = z.deflate(flush_Renamed_Field);
            else
                err = z.inflate(flush_Renamed_Field);

            // Z_STREAM_END -> end of stream is not an error, this is also in zlib.net 1.0.4
            // Z_BUF_ERROR  -> no data was available in the source stream is not an error,
            // this caused an exception in zlib.net 1.0.4
            // (see https://www.zlib.net/manual.html)
            if (err != zlib.zlibConst.Z_OK 
                && err != zlib.zlibConst.Z_STREAM_END 
                && err != zlib.zlibConst.Z_BUF_ERROR)
            {
                throw new zlib.ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
            }

            m_outStream.Write(buf, 0, bufsize - z.avail_out);
        }
        while (z.avail_in > 0 || z.avail_out == 0);
    }
}

为了比较,可以在 github 上查看 zlib.net 源代码。

© www.soinside.com 2019 - 2024. All rights reserved.