wake-up-neo.net

Wie verwende ich GZipStream mit System.IO.MemoryStream?

Ich habe ein Problem mit dieser Testfunktion, bei der ich eine In-Memory-Zeichenfolge nehme, komprimiere und dekomprimiere. Die Komprimierung funktioniert großartig, aber ich kann die Dekompression nicht zum Laufen bringen.

//Compress
System.IO.MemoryStream outStream = new System.IO.MemoryStream();                
GZipStream tinyStream = new GZipStream(outStream, CompressionMode.Compress);
mStream.Position = 0;
mStream.CopyTo(tinyStream);

//Decompress    
outStream.Position = 0;
GZipStream bigStream = new GZipStream(outStream, CompressionMode.Decompress);
System.IO.MemoryStream bigStreamOut = new System.IO.MemoryStream();
bigStream.CopyTo(bigStreamOut);

//Results:
//bigStreamOut.Length == 0
//outStream.Position == the end of the stream.

Ich glaube, dass bigStream out zumindest Daten enthalten sollte, insbesondere wenn mein Quellstream (outStream) gelesen wird. Ist das ein MSFT-Fehler oder meins?

39
random65537

Was in Ihrem Code geschieht, ist, dass Sie Streams öffnen, aber niemals schließen.

  • In Zeile 2 erstellen Sie eine GZipStream. Dieser Stream schreibt nichts in den zugrunde liegenden Stream, bis er der Meinung ist, es sei der richtige Zeitpunkt. Sie können es sagen, indem Sie es schließen.

  • Wenn Sie es jedoch schließen, wird auch der zugrunde liegende Stream (outStream) geschlossen. Daher können Sie mStream.Position = 0 nicht verwenden.

Sie sollten immer using verwenden, um sicherzustellen, dass alle Streams geschlossen werden. Hier ist eine Variation Ihres Codes, die funktioniert.

var inputString = "“ ... ”";
byte[] compressed;
string output;

using (var outStream = new MemoryStream())
{
    using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress))
    using (var mStream = new MemoryStream(Encoding.UTF8.GetBytes(inputString)))
        mStream.CopyTo(tinyStream);

    compressed = outStream.ToArray();
}

// “compressed” now contains the compressed string.
// Also, all the streams are closed and the above is a self-contained operation.

using (var inStream = new MemoryStream(compressed))
using (var bigStream = new GZipStream(inStream, CompressionMode.Decompress))
using (var bigStreamOut = new MemoryStream())
{
    bigStream.CopyTo(bigStreamOut);
    output = Encoding.UTF8.GetString(bigStreamOut.ToArray());
}

// “output” now contains the uncompressed string.
Console.WriteLine(output);
91
Timwi

Dies ist ein bekanntes Problem: http://blogs.msdn.com/b/bclteam/archive/2006/05/10/592551.aspx

Ich habe Ihren Code ein wenig geändert, damit dieser funktioniert:

var mStream = new MemoryStream(new byte[100]);
var outStream = new System.IO.MemoryStream();

using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress))
{
    mStream.CopyTo(tinyStream);           
}

byte[] bb = outStream.ToArray();

//Decompress                
var bigStream = new GZipStream(new MemoryStream(bb), CompressionMode.Decompress);
var bigStreamOut = new System.IO.MemoryStream();
bigStream.CopyTo(bigStreamOut);
32
Aliostad

Eine andere Implementierung in VB.NET:

Imports System.Runtime.CompilerServices
Imports System.IO
Imports System.IO.Compression

Public Module Compressor

    <Extension()> _
    Function CompressASCII(str As String) As Byte()

        Dim bytes As Byte() = Encoding.ASCII.GetBytes(str)

        Using ms As New MemoryStream

            Using gzStream As New GZipStream(ms, CompressionMode.Compress)

                gzStream.Write(bytes, 0, bytes.Length)

            End Using

            Return ms.ToArray

        End Using

    End Function

    <Extension()> _
    Function DecompressASCII(compressedString As Byte()) As String

        Using ms As New MemoryStream(compressedString)

            Using gzStream As New GZipStream(ms, CompressionMode.Decompress)

                Using sr As New StreamReader(gzStream, Encoding.ASCII)

                    Return sr.ReadToEnd

                End Using

            End Using

        End Using

    End Function

    Sub TestCompression()

        Dim input As String = "fh3o047gh"

        Dim compressed As Byte() = input.CompressASCII()

        Dim decompressed As String = compressed.DecompressASCII()

        If input <> decompressed Then
            Throw New ApplicationException("failure!")
        End If

    End Sub

End Module
5

Die Komprimierung und Dekomprimierung von und zu einer MemoryStream lautet:

public static Stream Compress(
    Stream decompressed, 
    CompressionLevel compressionLevel = CompressionLevel.Fastest)
{
    var compressed = new MemoryStream();
    using (var Zip = new GZipStream(compressed, compressionLevel, true))
    {
        decompressed.CopyTo(Zip);
    }

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

public static Stream Decompress(Stream compressed)
{
    var decompressed = new MemoryStream();
    using (var Zip = new GZipStream(compressed, CompressionMode.Decompress, true))
    {
        Zip.CopyTo(decompressed);
    }

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

Dadurch bleibt der komprimierte/dekomprimierte Stream offen und kann nach seiner Erstellung verwendet werden.

2
briantyler
    public static byte[] compress(byte[] data)
    {
        using (MemoryStream outStream = new MemoryStream())
        {
            using (GZipStream gzipStream = new GZipStream(outStream, CompressionMode.Compress))
            using (MemoryStream srcStream = new MemoryStream(data))
                srcStream.CopyTo(gzipStream);
            return outStream.ToArray();
        }
    }

    public static byte[] decompress(byte[] compressed)
    {
        using (MemoryStream inStream = new MemoryStream(compressed))
        using (GZipStream gzipStream = new GZipStream(inStream, CompressionMode.Decompress))
        using (MemoryStream outStream = new MemoryStream())
        {
            gzipStream.CopyTo(outStream);
            return outStream.ToArray();
        }
    }
1
PhonPanom

Wenn Sie versuchen, den MemoryStream zu verwenden (z. B. Weitergabe an eine andere Funktion), aber die Ausnahme erhalten, dass kein Zugriff auf einen geschlossenen Stream möglich ist. Dann gibt es noch einen anderen GZipStream-Konstruktor, den Sie verwenden können.

Durch Übergabe eines true an den leaveOpen-Parameter können Sie GZipStream anweisen, den Stream offen zu lassen, nachdem er sich selbst entsorgt hat. Standardmäßig wird der Zielstream geschlossen (was ich nicht erwartet hatte). https://msdn.Microsoft.com/de-de/library/27ck2z1y(v=vs.110).aspx

using (FileStream fs = File.OpenRead(f))
using (var compressed = new MemoryStream())
{
    //Instruct GZipStream to leave the stream open after performing the compression.
    using (var gzipstream = new GZipStream(compressed, CompressionLevel.Optimal, true))
        fs.CopyTo(gzipstream);

    //Do something with the memorystream
    compressed.Seek(0, SeekOrigin.Begin);
    MyFunction(compressed);
}
1
Snives

Wenn Sie es noch benötigen, können Sie den GZipStream-Konstruktor mit einem booleschen Argument (es gibt zwei solcher Konstruktoren) verwenden und dort den Wert true übergeben:

tinyStream = new GZipStream(outStream, CompressionMode.Compress, true);

Wenn Sie Ihren tynyStream schließen, bleibt Ihr Outstream in diesem Fall weiterhin geöffnet. Vergessen Sie nicht, Daten zu kopieren:

mStream.CopyTo(tinyStream);
tinyStream.Close();

Jetzt haben Sie einen Speicherstrom outStream mit gezippten Daten

Wanzen und Küsse für Sie

Viel Glück

0

Bitte beachten Sie den folgenden Link: Doppelte MemoryStream . https://stackoverflow.com/a/53644256/1979406 sollten nicht verwendet werden

0
Haryono