From Zip as Embedded Resource Stream to File?

Mar 4, 2009 at 10:22 PM
Edited Mar 4, 2009 at 11:30 PM
I have embedded several .mht help files in my application. These files are unloaded to a help directory when the application first runs.
I would like to 'compress' these files before compiling them as embedded  resources. I would then like to un-Zip them in the stream
used for their final file location.
How would this look in VB.net?
Mar 4, 2009 at 11:02 PM
Edited Mar 4, 2009 at 11:05 PM

I'm currenly using the following method to 'unpack' my help files ...

Private Sub RehydrateResourceToFile(ByVal resourceName As String, _
                                                                    
ByVal FileName As String)
    Dim buffer As Byte()
    Dim stream As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
   Using
reader As New BinaryReader(stream)
            buffer = reader.ReadBytes(
CInt(stream.Length))
            reader.Close()
    End Using 
    
Using output As New FileStream(FileName, FileMode.Create)
            output.Write(Buffer, 0, Buffer.Length)
            output.Close()
    End Using
End Sub

 

 

 

 

 

Coordinator
Mar 5, 2009 at 12:27 AM
couple things.
first, are you sure that the .mht file (or compiled help or whatever) is compressible?   It could be that it is already in a compressed format, which means runnnig it through DotNetZip will not compress it further.   It's worth checking.

Next - if you are storing your file as an embedded resource, and you want to unzip it with DotNetZip, you do not need to save the compressed thing to a file first.  You can unzip as you read  the bytes from the embedded resource, into the zip file.  Then just extract the files from there. 

I can provide code if you like.

Mar 5, 2009 at 2:07 AM
Thanks for your quick response.  I'll definately support your cause ...
Yes, I have tested the compression of these htlm files.
I author them in MSWord and I present them in a Browser control in a WinForm app.
On average they compress to half of the original size.
I've read all of your help file and I think I understand the technology. 
The help files mention that you can compress to and from Streams but I have yet to see any example that would
help my situation.  Would I replace my BinaryReader in the example above? Or, would I replace the FileStream?
Would I be better served just using System.IO.Compresssion?
Any example would be great.
Thanks again
Coordinator
Mar 5, 2009 at 4:04 AM
Edited Mar 5, 2009 at 4:07 AM
You could use System.IO.Compression.DeflateStream - it gives ok compression, and it is guaranteed, built in.  Compared to other deflate libraries, it doesn't compress as well.  A while back people asked me to move off of System.IO.Compression for just that reason.  So today, the DotNetZip has its own DeflateStream.  But System.IO.Compression may be good enough for you.  It's certainly easy -no need to repackage a library.  The space savings from not redistributing Ionic.Zip.dll (about 370k) may more than make up for the poorer compression you get from System.IO.Compression. 

I would say, use DeflateStream, or just a simple stream compressor, if you are dealing with one or two files at a time.  A zip archive is better if you are packing up a larger number of files together.  

To use the DeflateStream , you would do something like this:
    Dim working As Byte() = New Byte(4096)
    Dim n As Integer = 1
    Using input As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
        Using decompressor As Stream = New DeflateStream(input, CompressionMode.Decompress, True)
              Using output As FileStream = File.Create(Me._DecompressedFile)
                  Do While (n <> 0)
                      n = decompressor.Read(working, 0, working.Length)
                      If (n > 0) Then
                          output.Write(working, 0, n)
                      End If
                  Loop
              End Using
        End Using
    End Using

The result is a file, by the name stored in _DecompressedFile, on your disk. It is the decompressed version of whatever it was you embedded as a resource.

This means you have to compress the thing before embedding it, of course. Which you would do with code that sort of looks like the above, but slightly different:

    Using input As Stream = File.OpenRead(Me._FileToCompress)
        Using output As FileStream = File.Create(Me._CompressedFile)
            Using compressor As Stream = New DeflateStream(output, CompressionMode.Compress, True)
                Dim working As Byte() = New Byte(4096)
                Dim n As Integer = -1
                Do While (n <> 0)
                    If (n > 0) Then
                        compressor.Write(working, 0, n)
                    End If
                    n = input.Read(working, 0, working.Length)
                Loop
            End Using
        End Using
    End Using

You could maybe do that as a pre-build step in Visual Studio, before embedding the resource.

If you want to use DotNetZip and do the zipfile thing, I can show you that as well.  let me know.

Otherwise, Good luck!