0

I used the UnZipper class from this (How to unzip files in Windows Phone 8) post in my app for zips with images, but in some rare cases it gives me this error:

A first chance exception of type 'System.OutOfMemoryException' occurred in System.Windows.ni.dll System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at System.Windows.Application.GetResourceStreamInternal(StreamResourceInfo zipPackageStreamResourceInfo, Uri resourceUri) at System.Windows.Application.GetResourceStream(StreamResourceInfo zipPackageStreamResourceInfo, Uri uriResource) at ImperiaOnline.Plugins.UnZipper.GetFileStream(String filename) at ImperiaOnline.Plugins.IOHelpers.unzip(String zipFilePath, String zipDestinationPath)

The device has more then twice needed free memory. Can somebody help me with this. Here is my code:

public static void unzip(string zipFilePath,string zipDestinationPath) {
            using (IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                var dirNames = isolatedStorage.GetDirectoryNames(zipDestinationPath);
                bool doesFolderExists = (dirNames.Length > 0) ? true : false;
                if (!doesFolderExists)
                {
                    Debug.WriteLine("Folder does not exists");
                    isolatedStorage.CreateDirectory(zipDestinationPath);
                }
                try
                {
                    using (IsolatedStorageFileStream zipFile = isolatedStorage.OpenFile(zipFilePath, FileMode.Open, FileAccess.ReadWrite))
                    {
                        UnZipper unzip = new UnZipper(zipFile);
                        bool isModuleFolderDeleted = false;
                        foreach (string currentFileAndDirectory in unzip.FileNamesInZip())
                        {
                            string[] fileLocations = currentFileAndDirectory.Split('/');
                            string prefix = zipDestinationPath + '/';
                            int locationsCount = fileLocations.Length;
                            string fileName = fileLocations.Last();
                            string currentPath = prefix;
                            for (int i = 0; i < locationsCount - 1; i++)
                            {
                                dirNames = isolatedStorage.GetDirectoryNames(currentPath + fileLocations[i]);
                                doesFolderExists = (dirNames.Length > 0) ? true : false;
                                if (!doesFolderExists)
                                {
                                    isolatedStorage.CreateDirectory(currentPath + fileLocations[i]);
                                    if (i == 2)
                                    {
                                        isModuleFolderDeleted = true;
                                    }
                                }
                                else if (i == 2 && !isModuleFolderDeleted)
                                {
                                    Debug.WriteLine(currentPath + fileLocations[i] + " is deleted and recreated");
                                    DeleteDirectoryRecursively(isolatedStorage, currentPath + fileLocations[i]);
                                    isolatedStorage.CreateDirectory(currentPath + fileLocations[i]);
                                    isModuleFolderDeleted = true;
                                }
                                currentPath += fileLocations[i] + '/';
                            }
                            var newFileStream = isolatedStorage.CreateFile(currentPath + fileName);
                            byte[] fileBytes = new byte[unzip.GetFileStream(currentFileAndDirectory).Length];
                            unzip.GetFileStream(currentFileAndDirectory).Read(fileBytes, 0, fileBytes.Length);
                            unzip.GetFileStream(currentFileAndDirectory).Close();
                            try
                            {
                                newFileStream.Write(fileBytes, 0, fileBytes.Length);
                            }
                            catch (Exception ex)
                            {
                                Debug.WriteLine("FILE WRITE EXCEPTION: " + ex);
                                newFileStream.Close();
                                newFileStream = null;
                                zipFile.Close();
                                unzip.Dispose();
                            }
                            newFileStream.Close();
                            newFileStream = null;
                        }
                        zipFile.Close();
                        unzip.Dispose();
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                }

                isolatedStorage.DeleteFile(zipFilePath);
            }
        }

This error appears here:

var newFileStream = isolatedStorage.CreateFile(currentPath + fileName);
byte[] fileBytes = new byte[unzip.GetFileStream(currentFileAndDirectory).Length];                            unzip.GetFileStream(currentFileAndDirectory).Read(fileBytes, 0, fileBytes.Length);
unzip.GetFileStream(currentFileAndDirectory).Close();

I debugged it and it fails on

byte[] fileBytes = new byte[unzip.GetFileStream(currentFileAndDirectory).Length];

I checked GetFileStream method

public Stream GetFileStream(string filename)
        {
            if (fileEntries == null)
                fileEntries = ParseCentralDirectory(); //We need to do this in case the zip is in a format Silverligth doesn't like
            long position = this.stream.Position;
            this.stream.Seek(0, SeekOrigin.Begin);
            Uri fileUri = new Uri(filename, UriKind.Relative);
            StreamResourceInfo info = new StreamResourceInfo(this.stream, null);
            StreamResourceInfo stream = System.Windows.Application.GetResourceStream(info, fileUri);
            this.stream.Position = position;
            if (stream != null)
                return stream.Stream;
            return null;
        }

It throws OutOfMemory exception on this row:

StreamResourceInfo stream = System.Windows.Application.GetResourceStream(info, fileUri);
Community
  • 1
  • 1
ilian6806
  • 221
  • 1
  • 5
  • You're loading the entire contents of the file into `fileBytes`, which is why you're running out of memory. Instead of reading the entire thing, read chunks of the file (maybe 1000 bytes at at time) and write to the output file inside a loop until EOF. http://stackoverflow.com/questions/13607254/why-write-to-stream-in-chunks – Paul Abbott Jan 27 '15 at 18:59
  • I edit my post - it seems this is not the problem here :( – ilian6806 Jan 28 '15 at 14:19
  • Why won't you just write to new stream directly from original stream? – PTwr Jan 28 '15 at 14:38
  • Your code is not compilable - `for (int i = 0; i 0) ? true : false;` - can you fix it please? – Enigmativity Feb 28 '15 at 23:18

0 Answers0