Zip for WPF and Silverlight
C1Zip 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. Here is what the final application will look like:

     

     

    Step 1: Create the main form.

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

    Step 2: Add a reference to the C1.WPF.Zip or C1.Silverlight.Zip 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.WPF.Zip or C1.Silverlight.Zip assembly from the list, or browse to find the C1.WPF.Zip.dll or C1.Silverlight.Zip.dll file.

    Select the MainPage.xaml.vb or MainWindow.xaml.cs tab or go to View|Code to open the Code Editor. At the top of the file, add the following statements:

    Visual Basic
    Copy Code
    Imports System.IO
    Imports C1.C1Zip
    
    C#
    Copy Code
    using System.IO;
    using C1.C1Zip;
    

    This makes the objects defined in the C1.WPF.Zip, C1.Silverlight.Zip 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:

    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 disable the Expand button.

    Set the btnExpand.IsEnabled option to false with the following code below the InitializeComponent() method:

    btnExpand.IsEnabled = false;

    This code disables the Expand button until there are compressed files to expand.

    Step 5: Add code to compress files.

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

    C#
    Copy Code
    private void btnCompress_Click(object sender, RoutedEventArgs e)
            {
                // Get the application directory.   
                string appPath = Environment.CurrentDirectory;   
                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 + @"\" + System.IO.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 * 100.0 / size));      
                label1.Content = msg;      
                // Now we can expand.   
                btnExpand.IsEnabled = true;
            }
    

    The main line calls the utility function CompressFile utility method to compress each selected file. The compressed files are stored in the \compresseddirectory 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:

    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:

    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 6: Add code to expand files.

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

    C#
    Copy Code
    private void btnExpand_Click(object sender, RoutedEventArgs e)
            {    
                // Get the application directory.   
                string appPath = Environment.CurrentDirectory;   
                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 + @"\" + System.IO.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.Content = msg;
            }
    

    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:

    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.