Saturday, June 2, 2012

How to decompress files in Metro style applications?


In this blog post, I am going to demonstrate on how to use ZipArchive class in Metro style app to decompress a set of files and save the extracted files to a particular location.

Steps to decompress a set of files:

Step 1: Select the compressed file to decompress.

//Initialize file open picker
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.ViewMode = PickerViewMode.List;
//Suggest start location
fileOpenPicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
//Add file type filter
fileOpenPicker.FileTypeFilter.Add("*.zip");
//Opens file open picker to allow the user to select the compressed file
StorageFile stgFile = await fileOpenPicker.PickSingleFileAsync();

Step 2: Select folder to extract the files

//Initialize folder picker
FolderPicker saveFolder = new FolderPicker();
//Suggest start location
saveFolder.SuggestedStartLocation = PickerLocationId.Desktop;
//Add file type filter
saveFolder.FileTypeFilter.Add("*");
//Opens folder picker to allow the user to select the folder to extract the compressed items
StorageFolder storageFolder = await saveFolder.PickSingleFolderAsync();


Step 3: Use ZipArchive class to extract the files to the selected folder
//Read the stream from the compressed file
Stream stream = await stgFile.OpenStreamForReadAsync();
//Copy it to Memory stream for further manipulation
MemoryStream ms = new MemoryStream();
await stream.CopyToAsync(ms);
ms.Position = 0;

//Open Zip archive of the compressed file
zipArchive = new ZipArchive(ms, ZipArchiveMode.Read);

//For each archive entry, create file and folder accordingly and then copy the entry stream to the file.
foreach (ZipArchiveEntry entry in zipArchive.Entries)
{
StorageFile storageFile;
//Assign Selected save folder
StorageFolder stgFolder = storageFolder;
//Create Folder
stgFolder = await CreateFolder(storageFolder, entry.FullName.Replace(entry.Name, string.Empty));
//Create File
storageFile = await stgFolder.CreateFileAsync(entry.Name, CreationCollisionOption.ReplaceExisting);
//Open file stream for writing
Stream s = await storageFile.OpenStreamForWriteAsync();
//Copy the entry stream to the file stream
await entry.Open().CopyToAsync(s);
//Dispose
s.Dispose();
}
//Dispose
zipArchive.Dispose();
stream.Dispose();
ms.Dispose();

Helper methods:
Create folder based on the file path present in Zip Archive entry

async Task<StorageFolder> CreateFolder(StorageFolder stgFolder, string path)
{
//Split the folder path for creating sub folder
string[] locationSplit = path.Split(new char[] { '/' });
for (int i = 0; i < locationSplit.Length; i++)
{
//Create folder
if (locationSplit[i] != string.Empty)
stgFolder = await stgFolder.CreateFolderAsync(locationSplit[i], CreationCollisionOption.OpenIfExists);
}
return stgFolder;
}

Thus the files under the selected compressed file are extracted to a particular location.

References:
http://msdn.microsoft.com/en-us/library/windows/apps/br207928.aspx
http://msdn.microsoft.com/library/windows/apps/BR207847
http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.pickers.folderpicker.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/system.runtime.interopservices.windowsruntime.windowsruntimebufferextensions%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh454050%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/system.io.compression.ziparchive%28v=vs.110%29.aspx

No comments:

Post a Comment