Stream Not writing last byte?

Hello and thanks in advance for any help you may give. I am currently using the new gzip feature in VB 2005, to compress XML and insert the zipped bytes into an OLE access db column. I have gotten it to work for the most part except it seems to be cutting of the last Char of XML and sometimes even more. E.g. The closing tag of the XML would look like "</Inventory" - Missing the ">"  .I have no idea why, but since I am new to streams I may be missing something. So anyways here is my compression code. The top function is for compressing, the lower for decompressing -

Public Function GZipCompress(ByVal compressData As String)

Try

Dim buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(compressData)

Dim sr As New IO.MemoryStream()

Dim compressedzipStream As New GZipStream(sr, CompressionMode.Compress)

compressedzipStream.Write(buffer, 0, buffer.Length)

Return sr.ToArray

sr.Flush()

compressedzipStream.Flush()

compressedzipStream.Close()

sr.Close()

sr.Dispose()

destinationStream.Flush()

destinationStream.Close()


Catch
ex As Exception

MsgBox(ex.ToString)

End Try

End Function

'''''''''''''''''Decompressing

Public Function decomp(ByVal decompExp As Object)

Try

Dim abyt() As Byte

abyt = CType(decompExp, Byte())

Dim ms As New IO.MemoryStream(abyt)

Dim objZS As System.IO.Compression.GZipStream = New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)

Dim mem As New MemoryStream

Dim buffer As Byte() = New Byte(32767) {}

Dim bytesRead As Integer = 0

While True

bytesRead = objZS.Read(buffer, 0, buffer.Length)

If bytesRead > 0 Then

mem.Write(buffer, 0, bytesRead)

Else

Exit While

End If

End While

Dim sa As New IO.StringReader(System.Text.ASCIIEncoding.ASCII.GetString(mem.ToArray))

Return sa

ms.Flush()

ms.Close()

ms.Dispose()

mem.Flush()

mem.Close()

mem.Dispose()

objZS.Flush()

objZS.Close()

objZS.Dispose()

sa.Close()

sa.Dispose()

Catch ex As Exception

MsgBox(ex.ToString)

End Try

End Function





Answer this question

Stream Not writing last byte?

  • mike22

    In your GZipCompress function you are returning the results before you have flushed and closed your stream.  In order to guarantee that the stream contents are properly written you need to flush or close the stream before using it. 

    Note that you don't need to flush the stream if you close it because Close will automatically flush the stream first.  You also don't need to call Dispose if you have already called Close.  They both invoke the same method.  For classes that expose both you should normally just call Close as it makes more logical sense.

    Note also that your code is not exception safe.  If an exception occurs while operating on the stream you will leak memory and potentially lock a resource.  Here is my recommended update to your function.  You should modify your second function as well.

    Public Function GZipCompress(ByVal compressData As String)

    Dim sr As IO.MemoryStream
    Dim compressedzipStream As GZipStream
    Dim results() As Byte

    Try

    Dim buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(compressData)

    sr = New IO.MemoryStream()

    compressedzipStream = New GZipStream(sr, CompressionMode.Compress)

    compressedzipStream.Write(buffer, 0, buffer.Length)

    sr.Flush()
    Return
    sr.ToArray

    'sr.Flush()
    'compressedzipStream.Flush()
    'compressedzipStream.Close()
    'sr.Close()
    'sr.Dispose()
    'destinationStream.Flush()
    'destinationStream.Close()

    Catch
    ex As Exception

    MsgBox(ex.ToString)

    Finally
       'Close stream if it is opened - will automatically flush data
       If Not compressedzipStream Is Nothing
          compressedzipStream.Close()
      
       'Close extra memory stream
       If Not sr Is Nothing
          sr.Close()
    End
    Try

    End Function

    My VB isn't too great so you might need to make changes but in a nutshell it cleans up the resources (streams) in the finally block to guarantee that they are always properly cleaned up.  Notice that the return statement stays in this case because this is the last thing you are doing in the function.  However you have to flush the sr stream first otherwise you might not get all the data.

    Hope this helps,
    Michael Taylor - 11/11/05

  • Scottie J

    Hi all, i'm also facing some problem on filestream while i'm trying to Gzip a text file using VS 2005 system.io.compression. The code that i wrote work fine that it creates a zip file but the extension of the original file inside the zip file has been cut off. For example, the original file is Text.txt, after zip, the name of the file inside only left Text. Then I have to rename the file to Text.txt then can only i open the file.

    I included the code that i try out (download through internet) as below. Hope that someone can help me.

    Public Function compresserFichier(ByVal cheminSource As String, ByVal cheminDestination As String) As Boolean

    Try

    Dim monFileStream As FileStream

    monFileStream = New FileStream(cheminSource, FileMode.Open)

    Dim monBuffer As Byte()

    monBuffer = New Byte(monFileStream.Length) {}

    monFileStream.Read(monBuffer, 0, System.Convert.ToInt32(monFileStream.Length))

    monFileStream.Close()

    monFileStream = New FileStream(cheminDestination, FileMode.Create)

    Dim monGZipStream As GZipStream

    monGZipStream = New GZipStream(monFileStream, CompressionMode.Compress, False)

    monGZipStream.Write(monBuffer, 0, monBuffer.Length)

    monGZipStream.Close()

    monFileStream.Close()

    Return True

    Catch ex As Exception

    MessageBox.Show(ex.Message)

    Return False

    End Try

    End Function



  • John1984

    I actually have narrowed it down now, not to the actual compress/decompress, but when I am saving it to the database. For some reason when I am updating the db it cuts off part of the data.

    this is where I set the data to the dataset


    Me.InventorydbDataSet.Tables("webXml").Rows.Find(saveName).Item("xml9") = sr.toarray


    'sr.toarray is the byte array

     



    here is the update code


    Me.WebXmlBindingSource.EndEdit()

    Me.WebXmlTableAdapter.Update(Me.InventorydbDataSet.webXml)

    Me.InventorydbDataSet.webXml.AcceptChanges()

    Me.WebXmlTableAdapter.Fill(Me.InventorydbDataSet.webXml)



     

  • acplus

    Thank you for your reply. I changed the my code according to what you said, and also changed my decompression code to what I believe matches, but the problem still exists, which sucks lol. so here is my updated decompress code. Thanks again!



    Public Function decomp(ByVal decompExp As Object) As String

    Dim objZS As System.IO.Compression.GZipStream

    Dim mem As New MemoryStream

    Dim abyt() As Byte

    abyt = CType(decompExp, Byte())

    Dim ms As New IO.MemoryStream(abyt)

    Try

    objZS = New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)

     

    Dim buffer As Byte() = New Byte(32767) {}

    Dim bytesRead As Integer = 0

    While True

    bytesRead = objZS.Read(buffer, 0, buffer.Length)

    If bytesRead > 0 Then

    mem.Write(buffer, 0, bytesRead)

    Else

    Exit While

    End If

    End While

    ms.Flush()

    bind.Filter = Nothing

    Return System.Text.ASCIIEncoding.ASCII.GetString(mem.ToArray)

    Catch ex As Exception

    MsgBox(ex.ToString)

    Finally

    If Not objZS Is Nothing Then

    objZS.Close()

    End If

    If Not ms Is Nothing Then

    ms.Close()

    End If

    If Not mem Is Nothing Then

    mem.Close()

    End If

    End Try

    End Function



     


  • JerseyGRL1970

    Without some more info I'm not sure.  You seem to be trying to put a byte array into a row of a DataTable.  Do you mean to do that or do you want it as a string   If you want it as a string then you'll need to convert it first.

    I'm not sure what the WebXml thing you are using is other than perhaps a DataSet.  Did you verify that the column in the row contained all the data before you flushed it to the DB   It seems that maybe it isn't going to like the array.  What type is the column
    Why do you call Fill again   Is the row valid before you call Fill and invalid after   If so then maybe the underlying DataSet you are using is not pushing all the data out.

    Michael Taylor - 11/11/05

  • Nino Crudele

    Hi all,

    I think I have solve the problem that I post. For the last post I call the compresserFichier function through:

    m_objFile.compresserFichier("C:\\Test.txt", "D:\\Test.gz")

    Now I change the call to:

    m_objFile.compresserFichier("C:\\Test.txt", "D:\\Test.txt.gz")

    So for the zip name I want to use, I change it to original file name + .gz extension. So the Text.txt keep it's original file name and extension. But I don't really understand why it is like that, can someone help explain to me.

    Thanks all.



  • Stream Not writing last byte?