У меня проблемы с чтением сжатого (дефлированного) файла данных с использованием 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()
заставляет поток дефлагера очищать свои внутренние буферы. Флаг true
не позволяет ему закрыть базовый поток, который закрывается позже в Main()
. Те же изменения должны быть внесены и в метод Compress()
.