Add Ons - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Add Ons arrow Page 4 - Zipping Up Code with ZipForge
Zipping Up Code with ZipForge
By Jeff Cogswell

Rate This Article: Add This Article To:

Zipping Up Code with ZipForge - ' Streaming Files '
( Page 4 of 4 )

Streaming Files with ZipForge

At a basic level, ZipForge can be used to zip and unzip sets of files on the hard drive. But at a more sophisticated level, you can use to read data into a memory stream, making the data available for your program.

ADVERTISEMENT

Most applications need to read and write user files. Using persistent objects, you can easily write your data to a file, and then recreate your data when the file is opened. But with the help with a component such as ZipForge, you can represent your data as multiple files within a single zip archive file.

To demonstrate this concept, I wrote a simple function that saves user data to a single zip archive. The function saves a set of general metadata to one file within the zip archive. Next, the function saves the current user data to a new file within the archive, keeping all previous versions.

This could be useful if you're writing an application that needs to keep versions of previous files. I could think of many different reasons for this; for example, authors and editors often want several versions of a document available.

Here's the code, which I wrote in VB.NET:

Imports ComponentAce.Compression.ZipForge
Imports System.Collections.Generic

Module Module1

Structure UserDataInfo
  Public UpdateDate As DateTime
  Public Username As String
  Public DataVersion As Int32
  Public Sub WriteToStream(ByVal thestream As System.IO.Stream)
    Dim writer As New System.IO.BinaryWriter(thestream)
      writer.Write(UpdateDate.ToBinary)
      writer.Write(Username)
      writer.Write(DataVersion)
   End Sub
   Public Sub ReadFromStream(ByVal thestream As System.IO.Stream)
      Dim reader As New System.IO.BinaryReader(thestream)
      UpdateDate = DateTime.FromBinary(reader.ReadInt64)
      Username = reader.ReadString
      DataVersion = reader.ReadInt32
    End Sub
End Structure

Sub SaveToZip(ByVal TheUsername As String, _
  ByVal TheFile As String)
    Dim datainfo As New UserDataInfo
    datainfo.Username = TheUsername
    datainfo.DataVersion = 1
    Dim zip As New ZipForge
    zip.FileName = TheFile

   ' If archive exists, get metadata
    If System.IO.File.Exists(zip.FileName) Then
        zip.OpenArchive(System.IO.FileMode.Open)
       Dim archiveItem As _
           ComponentAce.Compression.ZipForge.ArchiveItem = _
           New ComponentAce.Compression.ZipForge.ArchiveItem()
       If zip.FindFirst("info.dat", archiveItem) Then
           Dim memstr As New System.IO.MemoryStream
           zip.ExtractToStream("info.dat", memstr)
           memstr.Seek(0, System.IO.SeekOrigin.Begin)
           datainfo.ReadFromStream(memstr)
           datainfo.DataVersion += 1
           memstr.Close()
        End If
       zip.CloseArchive()
    End If

    ' Save Options as one file in the archive
   If System.IO.File.Exists(zip.FileName) Then
       zip.OpenArchive(System.IO.FileMode.Open)
   Else
        zip.OpenArchive(System.IO.FileMode.Create)
   End If
   Dim outstr As New System.IO.MemoryStream
   datainfo.WriteToStream(outstr)
   zip.AddFromStream("info.dat", outstr)
   outstr.Close()

   ' Save next version of user data as another file in archive
   Dim dataname As String = "data\userdata" + _
        datainfo.DataVersion.ToString + ".dat"
   outstr = New System.IO.MemoryStream
   Dim outdata As New System.IO.BinaryWriter(outstr)
   ' Just some sample application data...
   outdata.Write(1)
   outdata.Write(100)
   outdata.Write("hello")
   outdata.Write("test")
   zip.AddFromStream(dataname, outstr)
   outstr.Close()

   zip.CloseArchive()

End Sub

Sub Main()
   SaveToZip("jeff", "c:\userdata.zip")
End Sub

End Module

This sample code only saves data; it does not read it. And I made up some random data that it writes out. But it demonstrates the concept. The first time the program is run it creates the zip archive file, and places in the archive the metadata file called info.dat. Then it writes the data out to a file called data\userdata1.dat.

The next time the program is run, it opens the existing .zip file, and reads in the info.dat metadata. Using the power of the .NET streams, the metadata goes into a structure I created called UserDataInfo. This structure includes a version number, which is incremented.

The UserDataInfo is then streamed back into the info.dat file, which is then re-written into the zip file. Finally, a new data file is written with the updated version number, such as data\userdata2.dat.

Figure 1. The zip file now contains metadata and three versions of the data.

The figure shows what the zip file looks like after three runs of the sample program. (I opened the file in WinZip to look at it.) You can see three different versions of the user data is present, and that they exist in a subdirectory called data.

Tip: In the sample program, I gave my archive file a .zip extension. However, if this routine were used in a commercial application, I would likely use a custom extension so that the zip file could be associated with my program. The ZipForge class, after all, doesn't require that the archive files have a .zip extension.

A Compressed Conclusion

ZipForge also has some other nice features which I didn't mention. For examle, you can do transaction processing, wherein you add files to a zip file, and then ultimately commit the changes, or, if you need to, undo the changes before they're committed to file. (That's much like a database feature.) That can definitely be handy. The control also has events that you can respond to. For example, in a GUI application, you can display a progress bar that's incremented as the zipping or unzipping takes place.

But do you even need ZipForge? As I alluded to earlier, the .NET framework includes the System.IO.Compression namespace, which contains two classes for compressing data, DeflateStream, and GZipStream. Comparing these classes to ZipForge, however, is comparing apples and oranges. These two .NET classes provide compression within a stream, and they only provide a single algorithm. ZipForge, however, reads and writes compressed data stored in the ZIP file format, and can use many different compression algorithms.

Also, I found on Microsoft's MSDN.com website a discussion questioning the performance of these two built-in .NET classes, as well as concerns about intellectual property licensing. (It might not be a concern, but you would want to talk it over with an attorney to be sure.)

Still, the native .NET DeflateStream and GZipStream classes might be all you want or need, if you're compressing data and then storing the data into a single file. If, however, you're reading multiple files all compressed and stored in a single ZIP file, these classes won't be enough. That's where a library such as ZipForge comes in.

I definitely was impressed with ZipForge and I certainly recommend it.



 
 
>>> More Add Ons Articles          >>> More By Jeff Cogswell
 



HD VOIP Has Arrived (with Tony Konstner)

Play Video >

All Videos >

Google and blonde jokes?

Read now >

Favorite books!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.