2010-09-15 13 views
35

मुझे इस टेस्ट फ़ंक्शन के साथ कोई समस्या है जहां मैं मेमोरी स्ट्रिंग में लेता हूं, इसे संपीड़ित करता हूं, और इसे डिकंप्रेस करता हूं। संपीड़न बहुत अच्छा काम करता है, लेकिन मुझे काम करने के लिए डिकंप्रेशन नहीं मिल रहा है।मैं System.IO.MemoryStream के साथ GZipStream का उपयोग कैसे करूं?

//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. 

मेरा मानना ​​है कि कम से कम उस में डेटा होना चाहिए कि bigStream बाहर है, खासकर यदि मेरे स्रोत धारा (outStream) पढ़ा जा रहा है। क्या यह एक एमएसएफटी बग या मेरा है?

उत्तर

84

आपके कोड में क्या होता है यह है कि आप स्ट्रीम खोलते रहते हैं, लेकिन आप उन्हें कभी बंद नहीं करते हैं।

  • लाइन 2 में, आप GZipStream बनाते हैं। यह धारा अंतर्निहित धारा में कुछ भी नहीं लिखेगी जब तक कि ऐसा लगता है कि यह सही समय नहीं है। आप इसे बंद करके इसे बता सकते हैं।

  • हालांकि, अगर आप इसे बंद करते हैं, तो यह अंतर्निहित धारा (outStream) को भी बंद कर देगा। इसलिए आप mStream.Position = 0 पर इसका उपयोग नहीं कर सकते हैं।

तुम हमेशा using का उपयोग सुनिश्चित करना है कि अपने सभी धाराओं को बंद कर दिया जाना चाहिए। यहां आपके कोड पर एक भिन्नता है जो काम करता है।

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); 
+7

+1 अच्छा जवाब Timwi। बस इसमें जोड़ने के लिए, GZip को डेटा के कुछ आंतरिक बफरिंग को संपीड़ित करने के लिए करने की आवश्यकता है। यह नहीं पता कि जब तक आप इसे बंद नहीं करते हैं तब तक यह डेटा प्राप्त कर लेता है और इसलिए यह अंतिम कुछ बाइट्स को थूक नहीं देता है और आंशिक स्ट्रीम विफल होने में विफल रहता है। – MerickOWA

+0

मुझे लगता है कि हम .NET 3.5 (एकता के साथ काम कर रहे हैं) पर हैं, इसलिए। कॉपी अभी तक मौजूद नहीं है। एक स्ट्रीम से दूसरी स्ट्रीम में कॉपी करने के लिए एसओ पर कहीं और दिख रहे हैं: http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances – Almo

+0

इसके लिए धन्यवाद, मैं रहा हूं दोनों दिशाओं में सही आउटपुट प्राप्त करने के लिए धाराओं को व्यवस्थित करने के तरीके को समझने में परेशानी हो रही है – MikeT

31

यह एक ज्ञात मुद्दा है: http://blogs.msdn.com/b/bclteam/archive/2006/05/10/592551.aspx

मैं अपने कोड बदल दिया है एक सा तो यह एक काम करता है:

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); 
4

एक और कार्यान्वयन, 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 
1
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

यदि आप प्रयास कर रहे हैं मेमोरीस्ट्रीम का उपयोग करने के लिए जी (उदा। इसे किसी अन्य फ़ंक्शन में पास करना) लेकिन अपवाद प्राप्त करना "बंद स्ट्रीम तक नहीं पहुंच सकता।" तो एक और GZipStream कन्स्ट्रक्टर है जिसका उपयोग आप कर सकते हैं जो आपकी मदद करेगा।

छुट्टी ओपन पैरामीटर के लिए एक सच्चाई में गुजरकर, आप स्वयं को निपटाने के बाद स्ट्रीम को खोलने के लिए GZipStream को निर्देश दे सकते हैं, डिफ़ॉल्ट रूप से यह लक्ष्य स्ट्रीम को बंद कर देता है (जिसे मैंने उम्मीद नहीं की थी)। https://msdn.microsoft.com/en-us/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); 
} 
2

तरह से सेक और करने के लिए और एक MemoryStream से संपीड़ित है:

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; 
} 

यह संकुचित/decompressed धारा खुला छोड़ देता है और इसे बनाने के बाद इस तरह के प्रयोग करने योग्य के रूप में।

संबंधित मुद्दे