1

AFAIK in Windows 10 Universal App you can now use the ZipFile class to decompress archives more easily than in Windows 8. However I can't quite figure out how exactly you open a Zip file from ApplicationData.Current.LocalFolder and extract the contents to the same location.

ZipFile.Open only takes a file location as a string which I'm not sure how to get.

Has anyone solved this yet?

Community
  • 1
  • 1
Thomas
  • 3,682
  • 4
  • 37
  • 74
  • 2
    Is there any reason, that you don't want to use the [ZipFile.ExtractToDirectory](https://msdn.microsoft.com/en-us/library/hh485723%28v=vs.110%29.aspx) method? – Herdo Dec 03 '15 at 09:29
  • Not at all, I just don't know how I can get the path of my file as a String - just as a StorageFile – Thomas Dec 03 '15 at 13:12
  • 1
    How about [StorageFile.Path](https://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.storagefile.path)? ;) – Herdo Dec 03 '15 at 14:16
  • thanks, you're right. I'm that familiar with StorageFiles ;-) – Thomas Dec 03 '15 at 16:01
  • @Herdo I thought System.IO is not to be used in UWP? – Dennis Schröer Oct 20 '16 at 06:39
  • @Zure It's `Windows.Storage`, not `System.IO` ;) – Herdo Oct 20 '16 at 15:41
  • @Herdo The ZipFile class is in System.IO and not Windows.Storage right? – freshWoWer Mar 19 '18 at 19:39
  • @freshWoWer The [ZipFile](https://docs.microsoft.com/de-de/dotnet/api/system.io.compression.zipfile?view=netframework-4.7.1) class is indeed in `System.IO` for the current .NET framework. Don't ask me why I referenced `Windows.Storage` 1.5 years ago :D – Herdo Mar 19 '18 at 20:41

2 Answers2

4

It's actually quite simple and as I've expected way shorter than dealing with streams! This is what worked for me. Notice I had to manually delete previously extracted files (in my case a single .json file) as you can't overwrite files using ZipFile.ExtractToDirectory.

    private async Task UnzipFile()
    {
        var localFolder = ApplicationData.Current.LocalFolder;
        var file = await localFolder.GetFileAsync("file.json");
        await file.DeleteAsync();
        var archive = await localFolder.GetFileAsync("archive.zip");
        ZipFile.ExtractToDirectory(archive.Path, localFolder.Path);
    }
Thomas
  • 3,682
  • 4
  • 37
  • 74
4

UWP ZIP

public class ZipArchiveManager
{
   /// <summary>
   /// Operation in IAsyncAction
   /// </summary>
   /// <param name="zipFile"></param>
   /// <param name="destinationFolder"></param>
   /// <param name="DeleteZipFileSource"></param>
   /// <returns></returns>
    public static async Task UnZipFileIAsync(StorageFile zipFile, StorageFolder destinationFolder, bool DeleteZipFileSource)
    {
        try
        {
            await UnZipFileHelperIAsync(zipFile, destinationFolder);
            if(zipFile != null && DeleteZipFileSource == true)
            {
                await zipFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
            }
        }
        catch (Exception ex)
        {
            Reporting.DisplayMessage("Failed to read file ..." + ex.Message);
        }
    }
    /// <summary>
    /// Operation just a awaitable task
    /// </summary>
    /// <param name="zipFile"></param>
    /// <param name="destinationFolder"></param>
    /// <param name="DeleteZipFileSource"></param>
    /// <returns></returns>
    public static async Task UnZipFileAsync(StorageFile zipFile, StorageFolder destinationFolder, bool DeleteZipFileSource)
    {
        try
        {
            await UnZipFileHelperAsync(zipFile, destinationFolder);
            if (zipFile != null && DeleteZipFileSource == true)
            {
                await zipFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
            }
        }
        catch (Exception ex)
        {
            Reporting.DisplayMessage("Failed to read file ..." + ex.Message);
        }
    }
    //IAsyncAction
    private static IAsyncAction UnZipFileHelperIAsync(StorageFile zipFile, StorageFolder destinationFolder)
    {
        return UnZipFileHelper(zipFile, destinationFolder).AsAsyncAction();
    }
    //Just Async
    private async static Task UnZipFileHelperAsync(StorageFile zipFile, StorageFolder destinationFolder)
    {
        await UnZipFileHelper(zipFile, destinationFolder).AsAsyncAction();
    }

    #region private helper functions 
    private static async Task UnZipFileHelper(StorageFile zipFile, StorageFolder destinationFolder)
    {
        var extension = zipFile.FileType;
        if (zipFile == null || destinationFolder == null ||
            !extension.Equals(".zip", StringComparison.CurrentCultureIgnoreCase)
            )
        {               
            throw new ArgumentException("Invalid argument..." + extension);
        }
        Stream zipMemoryStream = await zipFile.OpenStreamForReadAsync();
        // Create zip archive to access compressed files in memory stream 
        using (ZipArchive zipArchive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Read))
        {
            // Unzip compressed file iteratively. 
            foreach (ZipArchiveEntry entry in zipArchive.Entries)
            {
                await UnzipZipArchiveEntryAsync(entry, entry.FullName, destinationFolder);
            }
        }
    }
    /// <summary> 
    /// It checks if the specified path contains directory. 
    /// </summary> 
    /// <param name="entryPath">The specified path</param> 
    /// <returns></returns> 
    private static bool IfPathContainDirectory(string entryPath)
    {
        if (string.IsNullOrEmpty(entryPath))
        {
            return false;
        }
        return entryPath.Contains("/");
    }
    /// <summary> 
    /// It checks if the specified folder exists. 
    /// </summary> 
    /// <param name="storageFolder">The container folder</param> 
    /// <param name="subFolderName">The sub folder name</param> 
    /// <returns></returns> 
    private static async Task<bool> IfFolderExistsAsync(StorageFolder storageFolder, string subFolderName)
    {
        try
        {
            await storageFolder.GetFolderAsync(subFolderName);
        }
        catch (FileNotFoundException)
        {
            return false;
        }
        catch (Exception)
        {
            throw;
        }
        return true;
    }
    /// <summary> 
    /// Unzips ZipArchiveEntry asynchronously. 
    /// </summary> 
    /// <param name="entry">The entry which needs to be unzipped</param> 
    /// <param name="filePath">The entry's full name</param> 
    /// <param name="unzipFolder">The unzip folder</param> 
    /// <returns></returns> 
    private static async Task UnzipZipArchiveEntryAsync(ZipArchiveEntry entry, string filePath, StorageFolder unzipFolder)
    {
        if (IfPathContainDirectory(filePath))
        {
            // Create sub folder 
            string subFolderName = Path.GetDirectoryName(filePath);
            bool isSubFolderExist = await IfFolderExistsAsync(unzipFolder, subFolderName);
            StorageFolder subFolder;
            if (!isSubFolderExist)
            {
                // Create the sub folder. 
                subFolder =
                    await unzipFolder.CreateFolderAsync(subFolderName, CreationCollisionOption.ReplaceExisting);
            }
            else
            {
                // Just get the folder. 
                subFolder =
                    await unzipFolder.GetFolderAsync(subFolderName);
            }
            // All sub folders have been created. Just pass the file name to the Unzip function. 
            string newFilePath = Path.GetFileName(filePath);
            if (!string.IsNullOrEmpty(newFilePath))
            {
                // Unzip file iteratively. 
                await UnzipZipArchiveEntryAsync(entry, newFilePath, subFolder);
            }
        }
        else
        {
            // Read uncompressed contents 
            using (Stream entryStream = entry.Open())
            {
                byte[] buffer = new byte[entry.Length];
                entryStream.Read(buffer, 0, buffer.Length);
                // Create a file to store the contents 
                StorageFile uncompressedFile = await unzipFolder.CreateFileAsync
                (entry.Name, CreationCollisionOption.ReplaceExisting);
                // Store the contents 
                using (IRandomAccessStream uncompressedFileStream =
                await uncompressedFile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    using (Stream outstream = uncompressedFileStream.AsStreamForWrite())
                    {
                        outstream.Write(buffer, 0, buffer.Length);
                        outstream.Flush();
                    }
                }
            }
        }
    }
    #endregion

}
Amz
  • 51
  • 2