Вопрос по compression, c#, .net – Сжатие и распаковка потока с помощью Compression.DeflateStream

18

Я пытаюсь сжать и распаковать поток с помощьюCompression.DeflateStream, Сжатие, кажется, работает правильно, так как приведенный ниже код сжимает мой поток в массив длиной 110 байт. Однако чтение распакованного потока приводит к пустой строке.

class Program
{
    static void Main(string[] args)
    {
        // Compress a random string value
        string value = Path.GetRandomFileName();
        byte[] compressedBytes;

        using (var writer = new StreamWriter(new MemoryStream()))
        {
            writer.Write(value);
            writer.Flush();
            writer.BaseStream.Position = 0;

            compressedBytes = Compress(writer.BaseStream);
        }

        // Decompress compressed bytes
        Stream decompressedStream = Decompress(compressedBytes);
        // here already applies: decompressedStream.Length == 0

        using (var reader = new StreamReader(decompressedStream))
        {
            string decompressedValue = reader.ReadToEnd();

            if (value == decompressedValue)
                Console.WriteLine("Success");
            else
                Console.WriteLine("Failed");
        }
    }

    private static byte[] Compress(Stream input)
    {
        using (var compressStream = new MemoryStream())
        using (var compressor = new DeflateStream(compressStream, CompressionMode.Compress))
        {
            input.CopyTo(compressor);
            return compressStream.ToArray();
        }
    }

    private static Stream Decompress(byte[] input)
    {
        var output = new MemoryStream();

        using (var compressStream = new MemoryStream(input))
        using (var decompressor = new DeflateStream(compressStream, CompressionMode.Decompress))
            decompressor.CopyTo(output);

        output.Position = 0;
        return output;
    }
}

Может ли кто-нибудь помочь мне в этом? Большое спасибо.

Ваш Ответ

3   ответа
29

Compress функция:

private static byte[] Compress(Stream input)
{
    using(var compressStream = new MemoryStream())
    using(var compressor = new DeflateStream(compressStream, CompressionMode.Compress))
    {
        input.CopyTo(compressor);
        compressor.Close();
        return compressStream.ToArray();
    }
}

сжатый поток не был сброшен перед возвратом результирующего байтового массива.

Это работает. Большое спасибо greijner
@ Питер Очевиден в ретроспективе, молодец.
@Luke: отthe documentation for DeflateStream.Flush(): "The current implementation of this method does not flush the internal buffer. The internal buffer is flushed when the object is disposed." Что касается того, почему это дизайн,Stream.Flush() предназначен для очистки внутренней буферизации, но поток deflate не может быть завершен, пока он не узнает, что вы наend, что возможно только тогда, когда потокclosed.
Я должен был добавить третий параметрDeflateStream конструктор, чтобы заставить это работать.new DeflateStream(compressStream, CompressionMode.Compress, true) bool leaveOpen предотвращает закрытие потока памяти при закрытии компрессора.
Должен вызвать это, если вы звонитеFlush вместоClose это не работает. я думалClose призваниеFlush внутренне было почему это работает, а нет.
9

class Program
{
    static void Main(string[] args)
    {
        // Compress a random string value
        string value = DateTime.Now.ToLongTimeString();
        byte[] compressedBytes;

        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value)))
        {
            compressedBytes = Compress(stream);
        }


        // Decompress compressed bytes
        using (var decompressedStream = Decompress(compressedBytes))
        using (var reader = new StreamReader(decompressedStream))
        {
            string decompressedValue = reader.ReadToEnd();

            if (value == decompressedValue)
                Console.WriteLine("Success");
            else
                Console.WriteLine("Failed");
        }
    }

    public static byte[] Compress(Stream input)
    {
        using (var compressedStream = new MemoryStream())
        using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
        {
            input.CopyTo(zipStream);
            zipStream.Close();
            return compressedStream.ToArray();
        }
    }

    public static Stream Decompress(byte[] data)
    {
        var output = new MemoryStream();
        using(var compressedStream = new MemoryStream(data))
        using(var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
        {
            zipStream.CopyTo(output);
            zipStream.Close();
            output.Position = 0;
            return output;
        }
    }
}
Я использую те же функции сжатия, что и распаковка. Распаковка работает нормально, но возвращенный объект Stream дает мне. Невозможно получить доступ к закрытому потоку. сообщение, пока я пытаюсь его обработать. тот же код работал до сжатия распаковывать функции. любая идея?
8

потому что вы все забыли, что "используя" удаление и закрытие потоков означает, что дополнительный метод Close () не требуется. Я думаю, что идеальный код будет таким:

public static class CompressionHelper
{
    public static byte[] Compress(byte[] data)
    {
        byte[] compressArray = null;
        try
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress))
                {
                    deflateStream.Write(data, 0, data.Length);
                }
                compressArray = memoryStream.ToArray();
            }
        }
        catch (Exception exception)
        {
            // do something !
        }
        return compressArray;
    }

    public static byte[] Decompress(byte[] data)
    {
        byte[] decompressedArray = null;
        try
        {
            using (MemoryStream decompressedStream = new MemoryStream())
            {
                using (MemoryStream compressStream = new MemoryStream(data))
                {
                    using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress))
                    {
                        deflateStream.CopyTo(decompressedStream);
                    }
                }
                decompressedArray = decompressedStream.ToArray();
            }
        }
        catch (Exception exception)
        {
            // do something !
        }

        return decompressedArray;
    }
}

Похожие вопросы