I am working on a Windows Store app proof of concept that will open a .zip file and extract the contents to an app-specific Roaming folder. I have looked into several popular libraries to extract the contents only to find that these libraries don’t support Windows Store apps (at least not yet). So, I have decided to go with ZipArchive. I have the following code in a button click handler:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
var fileOpenPicker = new FileOpenPicker();
fileOpenPicker.FileTypeFilter.Add(".zip");
var openedFile = await fileOpenPicker.PickSingleFileAsync();
var booksFolder = await Windows.Storage.ApplicationData.Current.RoamingFolder.CreateFolderAsync("Stuff", CreationCollisionOption.OpenIfExists);
var folder = await booksFolder.CreateFolderAsync(openedFile.Name.Replace(".zip", string.Empty), CreationCollisionOption.ReplaceExisting);
using (var stream = await openedFile.OpenStreamForReadAsync())
{
using (var zip = new ZipArchive(stream, ZipArchiveMode.Read))
{
foreach (var entry in zip.Entries)
{
using (var entryStream = entry.Open())
{
var file = await folder.CreateFileAsync(entry.Name);
using (var decompressedStream = await file.OpenStreamForWriteAsync())
{
using (var deflateStream = new DeflateStream(entryStream, CompressionMode.Decompress))
{
await deflateStream.CopyToAsync(decompressedStream, (int)entry.Length);
}
}
}
}
}
}
}
However, I get an InvalidDataException on the line
await deflateStream.CopyToAsync(decompressedStream, (int)entry.Length);
Here’s the details of the exception:
System.IO.InvalidDataException was unhandled by user code
HResult=-2146233087
Message=Unknown block type. Stream might be corrupted.
Source=System
StackTrace:
at System.IO.Compression.DeflateStream.EndRead(IAsyncResult asyncResult)
at System.IO.Stream.<BeginEndReadAsync>b__e(Stream stream, IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.IO.Stream.<CopyToAsyncInternal>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at POC.MoviePlayer.GroupedItemsPage.<Button_Click_1>d__4.MoveNext() in c:\Users\Brent\Documents\Visual Studio 2012\Projects\POC.MoviePlayer\POC.MoviePlayer\GroupedItemsPage.xaml.cs:line 108
InnerException:
The .zip file I am trying to import was created with Windows Explorer’s Send To Compressed (Zipped) Folder option. I have also tried to create a .zip file in code, using ZipArchive, but I get more exceptions with that code too. Since that isn’t my ideal use case anyway, I won’t include my code to create the .zip unless it turns out to be useful to somebody.
I am hoping somebody can either see the error of my ways in the code above or provide a link to a solid library to work with zip files that is preferably open source. This frustrated developer would be very grateful for any help.
You don’t have to decompress the result of
entry.Open(). It is already decompressed.You could also use
ZipFileExtensions.ExtractToDirectory(http://msdn.microsoft.com/en-us/library/system.io.compression.zipfileextensions.extracttodirectory.aspx) to simplify your code.