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 Silverlight project in Visual Studio and from the Toolbox, add the following controls to the form:
• Four Button controls along the left edge of the form, as shown in the picture above. In the Properties window make the following changes:
Button |
Button.Content Property |
Button.Name Property |
Button.IsEnabled Property |
1 |
Open Source File |
btnOpenSourceFile |
True (Default) |
2 |
Save Compressed File |
btnSaveCompressedFile |
False |
3 |
Open Compressed File |
btnOpenCompressedFile |
False |
4 |
Save Expanded File |
btnSaveExpandedFile |
False |
Note that the Save Expanded File button cannot be used until we have some opened a compressed file to save.
• A Label control on the right of the buttons. This control will display statistics about the compression/expanding process.
Step 2: Add a reference to the 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.Silverlight.Zip assembly from the list, or browse to find the C1.Silverlight.Zip.dll file.
Select the MainPage.xaml.vb tab (MainPage.xaml.cs in C#) or go to View|Code to open the Code Editor. At the top of the file, add the following statements:
Imports System.IO
Imports C1.C1Zip
•C#
using System.IO;
using C1.C1Zip;
This makes the objects defined in the C1.Silverlight.Zip and System.IO assemblies visible to the project and saves a lot of typing.
Step 3: Add code to open the source file.
Add the following code to handle the Click event for the Open Source File command button:
•C#
private void btnOpenSourceFile_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dlgOpenFile = new OpenFileDialog();
if (dlgOpenFile.ShowDialog() == true)
{
srcStream = dlgOpenFile.File.OpenRead();
// Now we can expand.
btnSaveCompressedFile.IsEnabled = true;
}
}
Step 4: Add code to save the compressed file.
Add the following code to handle the Click event for the Save Compressed File command button:
•C#
private void btnSaveCompressedFile_Click(object sender, RoutedEventArgs e)
{
// Prepare to collect compression statistics.
long size = 0;
long sizeCompressed = 0;
long ticks = DateTime.Now.Ticks;
SaveFileDialog dlgSaveFile = new SaveFileDialog();
dlgSaveFile.Filter = "C1Zip Files (*.cmp) | *.cmp";
if (dlgSaveFile.ShowDialog() == true)
{
if (srcStream == null)
{
return;
}
Stream desStream = dlgSaveFile.OpenFile();
CompressFile(desStream, srcStream);
size = srcStream.Length;
sizeCompressed = desStream.Length;
// Always close our streams.
if (srcStream != null) srcStream.Close();
if (desStream != null) desStream.Close();
// Show stats.
string msg = string.Format("Compressed this file in {0} ms.\n\r" + "Original size: {1:#,###}\n\r" + "Compressed size: {2:#,###} ({3:0.00}% of original)", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, size, sizeCompressed, ((double)sizeCompressed / size) * 100.0);
label1.Content = msg;
this.btnOpenCompressedFile.IsEnabled = true;
}
}
Add the following code for the CompressFile function:
•C#
private bool CompressFile(Stream dstStream, FileStream srcStream)
{
// Prepare to compress file.
bool retval = true;
try
{
// 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;
}
// 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.
The StreamCopy function simply copies bytes from one stream to another. Here's the code:
•C#
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 open the compressed file.
Add the following code to handle the Click event for the Open Compressed File command button:
•C#
private void btnOpenCompressedFile_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dlgOpenFile = new OpenFileDialog();
dlgOpenFile.Filter = "C1Zip Files (*.cmp) | *.cmp";
if (dlgOpenFile.ShowDialog() == true)
{
srcStream = dlgOpenFile.File.OpenRead();
this.btnSaveExpandedFile.IsEnabled = true;
}
}
Step 6: Add code to save the expanded file.
Add the following code to handle the Click event for the Save Expanded File command button:
•C#
private void btnSaveExpandedFile_Click(object sender, RoutedEventArgs e)
{
// Prepare to collect compression statistics.
long size = 0;
long sizeExpanded = 0;
long ticks = DateTime.Now.Ticks;
SaveFileDialog dlgSaveFile = new SaveFileDialog();
if (dlgSaveFile.ShowDialog() == true)
{
if (srcStream == null)
{
return;
}
Stream desStream = dlgSaveFile.OpenFile();
ExpandFile(desStream, srcStream);
size = srcStream.Length;
sizeExpanded = desStream.Length;
// Always close our streams.
if (srcStream != null) srcStream.Close();
if (desStream != null) desStream.Close();
// Show stats.
string msg = string .Format("Expanded the file in {0} ms.\r\n" + "Original size: {1:#,###}\r\n" + "Expanded size: {2:#,###} ({3:0.00} x size of compressed)", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, size, sizeExpanded, (double)sizeExpanded / size);
label1.Content = msg;
// Now we can expand.
btnSaveCompressedFile.IsEnabled = true;
}
}
Here's the code for the ExpandFile function:
•C#
private bool ExpandFile(Stream dstStream, Stream srcStream)
{
// Prepare to expand file.
bool retval = true;
try
{
// 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;
}
// 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.