Search code examples
c#uwpzipstoragefile

Read the content of a zip file as a StorageFile object without extracting?


Still working on my slideshow project! Not too shabby, it now can read recursively a directory, display the files in sequence or random order, zoom in and out, respond to keyboard and mouse input.

I'm trying now to make it read the content of zip file without extracting it. As I am reading recursively the root directory given by a user as input, it stores all the files it encounteres as a list of StorageFile objects. I would like to be able to read the content of a zip file and add its files (that are images) to the list of StorageFile, and then eventually open and extract a single given file if it is the next in sequence or random order.

What I have found so far allows to extract the files on disk or to read the content of the zip file as a list of strings.

Am I clear on what I need? ANy idea how to do this?

Thanks! :)


Solution

  • Ok... got it!

    First, to read a specific entry, use ZipArchiveEntry.GetEntry(entrytosearch);

    Second, can't read a ZipArchiveEntry into a IRandomAccessStream, I don't know why... fiddled with it for a good while before deciding to read it in memory first. Since what I'm doing is read images to display on screen, it has limited memory management impact. However, beware of the size if you're reading something big. I would put a check on the .Length of the entry before reading it. However, for simplicty purposes, here is the updated code to read a specific ".jpg" entry of a zip file into a Image.Source.

    Not elegant or sophisticated yet, but i hope it saves someone the time I spent fiddling with this!

    public class ZipItem
    {
        public StorageFile motherfile { get; set; }
        public ZipArchiveEntry motherentry { get; set; }
        public string Name { get; set; }
        public string ActualBytes { get; set; }
        public string CompressedBytes { get; set; }
    }
    
    public List<ZipItem> results;
    public int i = 0;
    
    private async void  nextimg_Click(object sender, RoutedEventArgs e)
    {
        //Open the zip file. I previously stored all zip files and stored them in the "results" a list of ZipItems populated in another method
        Stream stream = await results[i].motherfile.OpenStreamForReadAsync();
    
        using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read))
        {
            //look for the entry "i", which is my current slideshow position
            ZipArchiveEntry entry = archive.GetEntry(results[i].motherentry.Name);
    
            //Open the entry as a stream
            Stream fileStream = entry.Open();
    
            //Before I read this in memory, I do check for entry.Length to make sure it's not too big. 
            //For simplicity purposes here, I jsut show the "Read it in memory" portion
            var memStream = new MemoryStream();
            await fileStream.CopyToAsync(memStream);
            //Reset the stream position to start
            memStream.Position = 0;
    
            //Create a BitmapImage from the memStream;
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.DecodePixelHeight = (int)ctlImage.Height;
            bitmapImage.DecodePixelWidth = (int)ctlImage.Width;
    
            //Set the source of the BitmapImage to the memory stream
            bitmapImage.SetSource(memStream.AsRandomAccessStream());
    
            //Set the Image.Source to the BitmapImage
            ctlImage.Source = bitmapImage;
            }
        }
    }