-1

I am writing some code to compress a byte array into a smaller byte array. Then I would like to decompress it:

''' <summary>
''' Receives bytes, returns compressed bytes.
''' </summary>
Function Compress(ByRef raw() As Byte) As Byte()
    Using memory As MemoryStream = New MemoryStream()
        Using gzip As GZipStream = New GZipStream(memory, CompressionMode.Compress)
            gzip.Write(raw, 0, raw.Length)
        End Using
        Return memory.ToArray()
    End Using
End Function

''' <summary>
''' Receives compressed bytes, returns bytes.
''' </summary>
Function DeCompress(ByRef compress() As Byte) As Byte()
    Using memory As MemoryStream = New MemoryStream()
        Using gzip As GZipStream = New GZipStream(memory, CompressionMode.Decompress)
            gzip.Write(compress, 0, compress.Length)
        End Using
        Return memory.ToArray()
    End Using
End Function

(I adopted this code from here)

My compression code works but my decompression code gives the following error:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.dll

Additional information: Writing to the compression stream is not supported.

I've tried many variations of gzip.Read and swapping around variables. (If I knew how to peer into the VB.NET inner source code, like I can with the JDK perhaps I could reverse engineer my way to a solutions, oh well)

How can I retool my DeCompress function to work as intended?

EDIT: I noticed I got down voted becuase I didn't show the .Read method use. Well I can't follow through with the .Read algo because my VB.NET does not have a .CopyTo() function. I don't understand why:

enter image description here

E.S.
  • 2,733
  • 6
  • 36
  • 71
  • 1
    When you are going to decompress, you don't write to the stream, you read from it – Camilo Terevinto Jan 22 '16 at 19:21
  • Possible duplicate of [GZipStream and decompression](http://stackoverflow.com/questions/1581694/gzipstream-and-decompression) – Camilo Terevinto Jan 22 '16 at 19:26
  • I wrote that I tried `gzip.Read` I didn't want to make my question 10 pages long with all my variations of tries.. Thanks for the down vote. – E.S. Jan 22 '16 at 19:31

2 Answers2

1

When you're decompressing, you're trying to write to the decompression stream. That's now how it works - when decompressing, it reads from the stream as you read the decompression stream.

Quick workaround demonstrated below:

''' <summary>
''' Receives bytes, returns compressed bytes.
''' </summary>
Function Compress(ByRef raw() As Byte) As Byte()
    Using memory As MemoryStream = New MemoryStream()
        Using gzip As GZipStream = New GZipStream(memory, CompressionMode.Compress)
            gzip.Write(raw, 0, raw.Length)
        End Using
        Return memory.ToArray()
    End Using
End Function

''' <summary>
''' Receives compressed bytes, returns bytes.
''' </summary>
Function DeCompress(ByRef compress() As Byte) As Byte()
    Using output As MemoryStream = New MemoryStream()
        Using memory As MemoryStream = New MemoryStream(compress)
            Using gzip As GZipStream = New System.IO.Compression.GZipStream(memory, CompressionMode.Decompress)
                CopyStreamToStream(gzip,output)
            End Using
            Return output.ToArray()
        End Using
    End Using
End Function


Public Shared Sub CopyStreamToStream(input As Stream, output As Stream)
    Dim buffer As Byte() = New Byte(16 * 1024 - 1) {}
    ' Fairly arbitrary size
    Dim bytesRead As Integer

    While (InlineAssignHelper(bytesRead, input.Read(buffer, 0, buffer.Length))) > 0
        output.Write(buffer, 0, bytesRead)
    End While
End Sub
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
    target = value
    Return value
End Function

Note that I now have "memory" reading from the "compress" byte array, and copying it to a new output stream.

Edit: Added a replacement for Stream.CopyTo(), as the questioner must work against .net 3.5

willaien
  • 2,647
  • 15
  • 24
  • I've seen code like this, and it didn't work. Namely, the `gzip.CopyTo()` function doesn't exist for me. I believe I am writing code compatible to .NET 3.5 so I don't understand why Visual Studio is yelling at me about `.CopyTo()` – E.S. Jan 22 '16 at 19:30
  • @E.S. `.CopyTo()` came in .net 4.0, if I'm not mistaken. I'll edit with a .net 3.5 compatible answer. – willaien Jan 22 '16 at 19:34
  • It worked! Thank you for the work around for `.CopyTo`! – E.S. Jan 22 '16 at 19:38
0

Example taken directly from the MSDN on the GZipStream Class:

Private Sub Decompress(ByVal fileToDecompress As FileInfo)
    Using originalFileStream As FileStream = fileToDecompress.OpenRead()
        Dim currentFileName As String = fileToDecompress.FullName
        Dim newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length)

        Using decompressedFileStream As FileStream = File.Create(newFileName)
            Using decompressionStream As GZipStream = New GZipStream(originalFileStream, CompressionMode.Decompress)
                decompressionStream.CopyTo(decompressedFileStream)
                Console.WriteLine("Decompressed: {0}", fileToDecompress.Name)
            End Using
        End Using
    End Using
End Sub

Look how the example reads from the decompresser stream while you attempt to write to it

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120