Исходный файл больше, чем распакованный файл GZip - PullRequest
1 голос
/ 24 февраля 2012

Итак, я пытаюсь сжать массив байтов (через поток). ExtendedStream - это просто класс, который я создал, который взаимодействует с базовым потоком (по умолчанию MemoryStream). Если я беру свои исходные данные, сжимаю их, распаковываю, а затем сравниваю размер распакованных данных с размером исходных данных (до сжатия), оказывается, что он меньше, чем исходные.

Исходная длина: 51695, сжатая длина: 26014, декомпрессированная длина: 48685.

Я храню тайлы (7 байт). Сжатие с использованием классов GZip, предоставленных в пространстве имен System.IO.Compression.

    public static ExtendedStream GZipDecompress(ExtendedStream stream)
    {
        ExtendedStream outStream = new ExtendedStream();
        GZipStream decompressStream = new GZipStream(stream.BaseStream, CompressionMode.Decompress, true);
        int b = -1;

        while ((b = decompressStream.ReadByte()) != -1)
        {
            outStream.WriteByte((Byte)b);
        }

        outStream.Seek(0, SeekOrigin.Begin);
        return outStream;
    }

    public static ExtendedStream GZipCompress(ExtendedStream stream)
    {
        ExtendedStream outStream = new ExtendedStream(); // base stream is a memorystream
        GZipStream compressStream = new GZipStream(outStream.BaseStream, CompressionMode.Compress, true);
        compressStream.Write(stream.ToArray(), 0, (int)stream.Length);
        compressStream.Flush();
        outStream.Seek(0, SeekOrigin.Begin);
        return outStream;
    }

Надеюсь, этого достаточно.

1 Ответ

1 голос
/ 24 февраля 2012

Вы должны закрыть поток сжатия; он не может записать все данные, пока вы этого не сделаете, из-за проблем с блоком:

public static ExtendedStream GZipCompress(ExtendedStream stream)
{
    ExtendedStream outStream = new ExtendedStream();
    using(var compressStream = new GZipStream(outStream.BaseStream, CompressionMode.Compress, false)) {
        compressStream.Write(stream.GetBuffer(), 0, (int)stream.Length);
    }
    outStream.Seek(0, SeekOrigin.Begin);
    return outStream;
}

Примечание: обычно я бы использовал CopyTo (или зацикливание вручную) для выполнения записи, но поскольку это основанный на памяти метод GetBuffer () дешевле.

Ваша декомпрессия может быть просто:

decompressStream.WriteTo(outStream);

Несмотря на это, самая большая проблема (которая вас здесь укусила) - не выбрасывать ваши одноразовые предметы. Вы должны сделать это; это требование API. Чтобы избежать преждевременной утилизации внешнего потока, передайте «false» конструктору GZipStream. Например:

using(var decompressStream = new GZipStream(stream.BaseStream, CompressionMode.Decompress, false)) {
    decompressionStream.CopyTo(outStream);
}
...