我在使用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;
}
解决
看到正确的解决方案后,构造函数语句应更改为:
inp = new DeflateStream(inp, CompressionMode.Decompress, true);
保持基础输入流打开,并且需要在inp.Flush()
调用后添加以下行:
inp.Close();
Close()
调用强制deflater流刷新其内部缓冲区。 true
标志阻止它关闭基础流,后者将在Main()
中关闭。同样的变化也应该用于Compress()
方法。
答案 0 :(得分:5)
在您的解压缩方法中,将inp重新分配给新的Stream(deflate流)。您永远不会关闭该Deflate流,但您确实在Main()中关闭了基础文件流。压缩方法也有类似的事情发生。
我认为问题是在deflate流的终结器自动关闭之前,底层文件流正在关闭。
我在你的Decompress和Compress方法中添加了一行代码: inp.Close()//到Decompressmehtod
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;
}
答案 1 :(得分:0)
我遇到了与GZipStream相同的问题,因为我们已经存储了原始长度,所以我必须重新编写代码才能读取原始文件中预期的字节数。
希望我能够知道有更好的答案(手指交叉)。