代码之家  ›  专栏  ›  技术社区  ›  David R Tribble

用deflatestream解压数据文件

  •  6
  • David R Tribble  · 技术社区  · 15 年前

    我在使用C.NET读取压缩(放气)数据文件时遇到问题 DeflateStream(..., CompressionMode.Decompress) . 文件是使用 DeflateStream(..., CompressionMode.Compress) 它看起来很好(我甚至可以用Java程序解压它)。

    但是,第一个 Read() 调用输入流以解压缩/膨胀压缩数据,返回长度为零(文件结尾)。

    下面是用于压缩和解压缩的主驱动程序:

    public void Main(...)
    {
        Stream  inp;
        Stream  outp;
        bool    compr;  
    
        ...
        inp = new FileStream(inName, FileMode.Open, FileAccess.Read);
        outp = new FileStream(outName, FileMode.Create, FileAccess.Write);  
    
        if (compr)
            Compress(inp, outp);
        else
            Decompress(inp, outp);  
    
        inp.Close();
        outp.Close();
    }
    

    以下是解压的基本代码,这就是失败的原因:

    public long Decompress(Stream inp, Stream outp)
    {
        byte[]  buf = new byte[BUF_SIZE];
        long    nBytes = 0;  
    
        // Decompress the contents of the input file
        inp = new DeflateStream(inp, CompressionMode.Decompress);  
    
        for (;;)
        {
            int   len;  
    
            // Read a data block from the input stream
            len = inp.Read(buf, 0, buf.Length);    //<<FAILS
            if (len <= 0)
                break;  
    
            // Write the data block to the decompressed output stream
            outp.Write(buf, 0, len);
            nBytes += len;
        }  
    
        // Done
        outp.Flush();
        return nBytes;
    }
    

    呼叫标记 FAILS 总是返回零。为什么?我知道这一定很简单,但我只是看不见而已。

    下面是压缩的基本代码,它工作得很好,几乎与交换名称的解压缩方法完全相同:

    public long Compress(Stream inp, Stream outp)
    {
        byte[]  buf = new byte[BUF_SIZE];
        long    nBytes = 0;  
    
        // Compress the contents of the input file
        outp = new DeflateStream(outp, CompressionMode.Compress);  
    
        for (;;)
        {
            int   len;  
    
            // Read a data block from the input stream
            len = inp.Read(buf, 0, buf.Length);
            if (len <= 0)
                break;  
    
            // Write the data block to the compressed output stream
            outp.Write(buf, 0, len);
            nBytes += len;
        }  
    
        // Done
        outp.Flush();
        return nBytes;
    }  
    

    解决了的

    看到正确的解决方案后,constructor语句应更改为:

    inp = new DeflateStream(inp, CompressionMode.Decompress, true);
    

    它使底层输入流保持打开状态,并且需要在 inp.Flush() 呼叫:

    inp.Close();
    

    这个 Close() 调用强制放气流刷新其内部缓冲区。这个 true 标志阻止它关闭基础流,该流稍后在 Main() . 也应该对 Compress() 方法。

    2 回复  |  直到 15 年前
        1
  •  5
  •   JMarsch    15 年前

    在解压方法中,正在将INP重新分配给新流(放气流)。永远不要关闭该放气流,但要关闭main()中的基础文件流。压缩方法中也发生了类似的事情。

    我认为问题在于,在deflate流的终结器自动关闭它们之前,底层文件流正在被关闭。

    我在您的解压缩和压缩方法中添加了1行代码: inp.close()//到compressmehtod

    outp.close()//到compress方法。

    更好的做法是将流封闭在using子句中。

    下面是编写解压方法的另一种方法(我测试过,它可以工作)

    
        public static long Decompress(Stream inp, Stream outp)
        {
            byte[]  buf = new byte[BUF_SIZE];
            long    nBytes = 0;  
    
            // Decompress the contents of the input file
            using (inp = new DeflateStream(inp, CompressionMode.Decompress))
            {
                int len;
                while ((len = inp.Read(buf, 0, buf.Length)) > 0)
                {
                    // Write the data block to the decompressed output stream
                    outp.Write(buf, 0, len);
                    nBytes += len;
                }  
            }
            // Done
            return nBytes;
        }
        
    
        2
  •  0
  •   csharptest.net    15 年前

    gzipstream也有同样的问题,因为我们存储了原始长度,所以我必须重新编写代码,以只读取原始文件中预期的字节数。

    希望我即将知道有一个更好的答案(手指交叉)。