ComponentOne Zip for .NET
Zip for .NET Tutorials / Compressing Files
In This Topic
    Compressing Files
    In This Topic

    This tutorial shows how you can compress and expand individual files. Note that these are not zip files; they are just compressed streams on disk. Zip files are covered in the Handling Zip Files tutorial. Here is what the final application will look like:


    Step 1: Create the main form.

    Start a new Visual Studio project and from the Toolbox, add the following controls to the form:

    Step 2: Add a reference to the C1Zip assembly.

    Go to the Solution Explorer window and click the Show All Files button. Right-click on References, and select the Add Reference menu option. Select the C1.C1Zip assembly from the list, or browse to find the C1.C1Zip.2.dll file.

    Select the Form1.vb tab (Form1.cs in C#) or go to View|Code to open the Code Editor. At the top of the file, add the following statements:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Imports System.IO
    Imports C1.C1Zip
    

    To write code in C#

    C#
    Copy Code
    using System.IO;
    using C1.C1Zip;
    

    This makes the objects defined in the C1Zip and System.IO assemblies visible to the project and saves a lot of typing.

    Step 3: Define the directory names for the compressed and expanded files.

    In the Code Editor of the form, define the following constants:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Private Const DIR_COMP = "\compressed"
    Private Const DIR_EXP = "\expanded"
    

    To write code in C#

    C#
    Copy Code
    private const string DIR_COMP = @"\compressed";
    private const string DIR_EXP = @"\expanded";
    

    These are the directory names where the compressed and expanded files will be stored (relative to the directory where the tutorial application is located on your disk).

    Step 4: Add code to compress files.

    Add the following code to handle the Click event for the Compress Files command button:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Private Sub btnCompress_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCompress.Click
         ' Get the application directory.
        Dim appPath As String = Application.ExecutablePath
        Dim i As Integer = appPath.IndexOf("\bin\")
        If i > 0 Then appPath = appPath.Substring(0, i)
         ' Create a directory for compressed files.
        If (Directory.Exists(appPath + DIR_COMP)) Then
            Directory.Delete(appPath + DIR_COMP, True)
        End If
        Directory.CreateDirectory(appPath + DIR_COMP)
         ' Prepare to collect compression statistics.
        Dim count As Long
        Dim size As Long
        Dim sizeCompressed As Long
        Dim ticks As Long = DateTime.Now.Ticks
         ' Compress all files in the application dir into the compressed dir.
        Dim files As String() = Directory.GetFiles(appPath)
        Dim srcFile As String
        For Each srcFile In files
            Dim dstFile As String
            dstFile = appPath + DIR_COMP + "\" + Path.GetFileName(srcFile) + ".cmp"
             ' Compress file.
            CompressFile(dstFile, srcFile)
             ' Update stats.
            count = count + 1
            size = size + New FileInfo(srcFile).Length
            sizeCompressed = sizeCompressed + New FileInfo(dstFile).Length
        Next srcFile
         ' Show stats.
        Dim msg As String = String.Format("Compressed {0} files in {1} ms." & vbCrLf & "Original size:   {2:#,###}" & vbCrLf & "Compressed size: {3:#,###} ({4:0.00}% of original)", count, (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, size, sizeCompressed, (sizeCompressed / size) * 100.0)
        Label1.Text = msg
         ' Now we can expand.
        btnExpand.Enabled = True
    End Sub
    

    To write code in C#

    C#
    Copy Code
    private void btnCompress_Click(object sender, EventArgs e)
    {
         // Get the application directory.
        string appPath = Application.ExecutablePath;
        int i = appPath.IndexOf(@"\bin\");
        if (i > 0) appPath = appPath.Substring(0, i);
           // Create a directory for compressed files.
        if ((Directory.Exists(appPath + DIR_COMP)))
            Directory.Delete(appPath + DIR_COMP, true);
        Directory.CreateDirectory(appPath + DIR_COMP);
           // Prepare to collect compression statistics.
        long count = 0;
        long size = 0;
        long sizeCompressed = 0;
        long ticks = DateTime.Now.Ticks;
           // Compress all files in the application dir into the compressed dir.
        foreach (string srcFile in Directory.GetFiles(appPath))
        {
            string dstFile = appPath + DIR_COMP + @"\" + Path.GetFileName(srcFile) + ".cmp";
               // Compress file.
            CompressFile(dstFile, srcFile);
               // Update stats.
            count++;
            size += new FileInfo(srcFile).Length;
            sizeCompressed += new FileInfo(dstFile).Length;
        }
           // Show stats.
        string  msg = string .Format("Compressed {0} files in {1} ms.\n\r" + "Original size:   {2:#,###}\n\r" + "Compressed size: {3:#,###} ({4:0.00}% of original)", count, (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, size, sizeCompressed, (sizeCompressed / size) * 100.0);
        label1.Text = msg;
           // Now we can expand.
        btnExpand.Enabled = true;
    }
    

    The main line calls the utility function CompressFile utility method to compress each selected file. The compressed files are stored in the \compressed directory under the application folder. They have the same name as the original file, plus a CMP extension.

    Add the following code for the CompressFile function:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Private Function CompressFile( dstFile As String, srcFile As String) As Boolean
         ' Prepare to compress file.
        Dim retval As Boolean = True
        Dim srcStream As FileStream = Nothing
        Dim dstStream As FileStream = Nothing
        Try
             ' Open the files.
            srcStream = New FileStream(srcFile, FileMode.Open, FileAccess.Read)
            dstStream = New FileStream(dstFile, FileMode.Create, FileAccess.Write)
             ' Open a compressor stream on the destination file.
            Dim sw As C1ZStreamWriter = New C1ZStreamWriter(dstStream)
             ' Copy the source into the compressor stream.
            StreamCopy(sw, srcStream)
        Catch
             ' Exception? Tell the caller we failed.
            retval = False
         Finally
             ' Always close our streams.
            If Not (srcStream Is Nothing) Then srcStream.Close()
            If Not (dstStream Is Nothing) Then dstStream.Close()
        End Try
         ' Done.
        CompressFile = False
    End Function
    

    To write code in C#

    C#
    Copy Code
    private bool CompressFile(string  dstFile, string  srcFile)
    {
         // Prepare to compress file.
        bool retval = true;
        FileStream srcStream = null;
        FileStream dstStream = null;
        try
        {
             // Open the files.
            srcStream = new FileStream(srcFile, FileMode.Open, FileAccess.Read);
            dstStream = new FileStream(dstFile, FileMode.Create, FileAccess.Write);
             // Open a compressor stream on the destination file.
            C1ZStreamWriter sw = new C1ZStreamWriter(dstStream);
             // Copy the source into the compressor stream.
            StreamCopy(sw, srcStream);
        }
        catch 
        {
             // Exception? Tell the caller we failed.
            retval = false;
        }
        finally 
        {
             // Always close our streams.
            if (srcStream != null) srcStream.Close();
            if (dstStream != null) dstStream.Close();
        }
         // Done.
        return false;
    }
    

    The function starts by creating two new file streams: one for the source file and one for the compressed file. Then it creates a C1ZStreamWriter object and attaches it to the destination stream. Next, it calls the StreamCopy function to transfer data from the source file and write it into the compressor stream.

    Finally, the function closes both streams. Note the use of the Finally statement to ensure that both streams are properly closed even if there are exceptions while the function is executing.

    The StreamCopy function simply copies bytes from one stream to another. Here's the code:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Private Sub StreamCopy(dstStream As Stream, srcStream As Stream)
        Dim buffer(32768) As Byte
        Dim read As Integer
        Do
            read = srcStream.Read(buffer, 0, buffer.Length)
            dstStream.Write(buffer, 0, read)
        Loop While read > 0
        dstStream.Flush()
    End Sub
    

    To write code in C#

    C#
    Copy Code
    private void StreamCopy(Stream dstStream, Stream srcStream) 
    {
        byte[] buffer= new byte[32768];
        for (;;)
        {
            int read = srcStream.Read(buffer, 0, buffer.Length);
            if (read == 0) break;
            dstStream.Write(buffer, 0, read);
        }
        dstStream.Flush();
    }
    

    Note that the function calls the Flush method after it is done to ensure that any cached data is written out when the function is done copying. This is especially important when dealing with compressed streams, since they cache substantial amounts of data in order to achieve good compression rates.

    Step 5: Add code to expand files.

    Add the following code to handle the Click event for the Expand Files command button:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Private Sub btnExpand_Click(sender As Object, e As EventArgs) Handles btnExpand.Click
         ' Get the application directory.
        Dim appPath As String = Application.ExecutablePath
        Dim i As Integer      = appPath.IndexOf("\bin\")
        If i > 0 Then appPath = appPath.Substring(0, i)
         ' Create a directory for expanded files.
        If Directory.Exists(appPath + DIR_EXP) Then
            Directory.Delete(appPath + DIR_EXP, True)
        End If
        Directory.CreateDirectory(appPath + DIR_EXP)
         ' Prepare to collect compression statistics.
        Dim count As Long
        Dim size As Long
        Dim sizeExpanded As Long
        Dim ticks As Long = DateTime.Now.Ticks
         ' Expand all files in the "compressed" dir to the "expanded" dir.
        Dim srcFile As String
        Dim files As String()
        files = Directory.GetFiles(appPath + DIR_COMP)
        For Each srcFile In files
             ' Expand file.
            Dim dstFile As String = appPath + DIR_EXP + "\" + Path.GetFileName(srcFile)
            dstFile = dstFile.Replace(".cmp", "")
            ExpandFile(dstFile, srcFile)
             ' Update stats.
            count = count + 1
            size = size + New FileInfo(srcFile).Length
            sizeExpanded = sizeExpanded + New FileInfo(dstFile).Length
        Next srcFile
         ' Show stats.
        Dim msg As String
        msg = String.Format("Expanded {0} files in {1} ms." & vbCrLf & "Original size:   {2:#,###}" & vbCrLf & "Expanded size: {3:#,###} ({4:0.00} x size of compressed)", count, (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, size, sizeExpanded, sizeExpanded / size)
        Label1.Text = msg
    End Sub
    

    To write code in C#

    C#
    Copy Code
    private void btnExpand_Click(object sender, EventArgs e)
    {
         // Get the application directory.
        string appPath = Application.ExecutablePath;
        int i = appPath.IndexOf(@"\bin\");
        if (i > 0) appPath = appPath.Substring(0, i);
         // Create a directory for expanded files.
        if (Directory.Exists(appPath + DIR_EXP))
            Directory.Delete(appPath + DIR_EXP, true);
        Directory.CreateDirectory(appPath + DIR_EXP);
         // Prepare to collect compression statistics.
        long count = 0;
        long size = 0;
        long sizeExpanded = 0;
        long ticks = DateTime.Now.Ticks;
         // Expand all files in the "compressed" dir to the "expanded" dir.
        foreach (string srcFile in Directory.GetFiles(appPath + DIR_COMP))
        {
             // Expand file.
            string  dstFile = appPath + DIR_EXP + @"\" + Path.GetFileName(srcFile);
            dstFile = dstFile.Replace(".cmp", "");
            ExpandFile(dstFile, srcFile);
             // Update stats.
            count++;
            size += new FileInfo(srcFile).Length;
            sizeExpanded += new FileInfo(dstFile).Length;
        }
         // Show stats.
        string msg = string .Format("Expanded {0} files in {1} ms.\r\n" + "Original size:   {2:#,###}\r\n" + "Expanded size: {3:#,###} ({4:0.00} x size of compressed)", count, (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, size, sizeExpanded, sizeExpanded / size);
        label1.Text = msg;
    }
    

    The main line calls the utility function ExpandFile utility method to expand the files that were compressed earlier. The expanded files are stored in the \expanded directory under the application folder. They have the same name as the original file, minus the CMP extension.

    Here's the code for the ExpandFile function:

    To write code in Visual Basic

    Visual Basic
    Copy Code
    Private Function ExpandFile(dstFile As String, srcFile As String) As Boolean
         ' Prepare to expand file.
        Dim retval As Boolean = True
        Dim srcStream As FileStream = Nothing
        Dim dstStream As FileStream = Nothing
        Try
             ' Open the files.
            srcStream = New FileStream(srcFile, FileMode.Open, FileAccess.Read)
            dstStream = New FileStream(dstFile, FileMode.Create, FileAccess.Write)
             ' Open an expander stream on the compressed source.
            Dim sr As C1ZstreamReader = New C1ZStreamReader(srcStream)
             ' Copy the expander stream into the destination file.
            StreamCopy(dstStream, sr)
        Catch
             ' Exception? Tell the caller we failed.
            retval = False
        Finally
             ' Always close our streams.
            If Not (srcStream Is Nothing) Then srcStream.Close()
            If Not (dstStream Is Nothing) Then dstStream.Close()
        End Try
       ' Done.
      ExpandFile = retval
    End Sub
    

    To write code in C#

    C#
    Copy Code
    private bool ExpandFile(string dstFile, string srcFile)
    {
         // Prepare to expand file.
        bool retval = true;
        FileStream srcStream = null;
        FileStream dstStream = null;
        try 
        { 
            // Open the files.
            srcStream = new FileStream(srcFile, FileMode.Open, FileAccess.Read);
            dstStream = new FileStream(dstFile, FileMode.Create, FileAccess.Write);
             // Open an expander stream on the compressed source.
            C1ZStreamReader sr = new C1ZStreamReader(srcStream);
             // Copy the expander stream into the destination file.
            StreamCopy(dstStream, sr);
        }
        catch
        {
             // Exception? Tell the caller we failed.
            retval = false;
        }
        finally
        {
             // Always close our streams.
            if (srcStream != null) srcStream.Close();
            if (dstStream != null) dstStream.Close();
        }
         // Done.
        return retval;
    }
    

    The function is similar to CompressFile, except it attaches a C1ZStreamReader to the source stream instead of attaching a C1ZStreamWriter to the destination stream.

    This concludes the Compressing Files tutorial.