Считать содержимое zip-файла как объект StorageFile без извлечения? - PullRequest
0 голосов
/ 05 сентября 2018

Все еще работаю над моим проектом слайд-шоу! Не слишком потрепанный, теперь он может рекурсивно читать каталог, отображать файлы в последовательном или произвольном порядке, увеличивать и уменьшать масштаб, реагировать на ввод с клавиатуры и мыши.

Сейчас я пытаюсь заставить его читать содержимое zip-файла, не распаковывая его. Поскольку я рекурсивно читаю корневой каталог, заданный пользователем в качестве входных данных, он хранит все файлы, с которыми встречается, в виде списка объектов StorageFile. Я хотел бы иметь возможность читать содержимое zip-файла и добавлять его файлы (которые являются изображениями) в список StorageFile, а затем в конечном итоге открывать и извлекать один заданный файл, если он следующий по порядку или в случайном порядке.

То, что я нашел до сих пор, позволяет извлечь файлы на диск или прочитать содержимое zip-файла в виде списка строк.

Я понимаю, что мне нужно? Любая идея, как это сделать?

Спасибо! :)

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Хорошо ... понял!

Сначала, чтобы прочитать конкретную запись, используйте ZipArchiveEntry.GetEntry (entrytosearch);

Во-вторых, я не могу прочитать ZipArchiveEntry в IRandomAccessStream, я не знаю почему ... возился с ним некоторое время, прежде чем решил сначала прочитать его в памяти. Поскольку то, что я делаю, - это чтение изображений для отображения на экране, это оказывает ограниченное влияние на управление памятью. Однако остерегайтесь размера, если вы читаете что-то большое. Я бы поставил галочку на. Длине записи, прежде чем читать ее. Однако, для упрощения, здесь приведен обновленный код для чтения определенной записи ".jpg" файла zip в Image.Source.

Пока еще не элегантно или изысканно, но я надеюсь, что это сэкономит кому-то время, которое я потратил на эту игру!

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;
        }
    }
}
0 голосов
/ 08 сентября 2018

Хорошо, я дошел до открытия zip-файлов, чтения их содержимого ZipArchiveEntry и создания списка в памяти ZipArchiveEntries. Однако я застрял на двух вещах:

1) Как заново открыть ZipArchive и получить доступ к определенной ZipArchiveEntry в моем списке?

2) Как я могу прочитать тот ZipArchiveEntry, который является изображением .jpg, в BitmapImage, чтобы отобразить его в Image.Source?

Вот пример кода, и он не работает! лол!

    public class ZipItem
    {
        public StorageFile motherfile { get; set; }  //Source File
        public ZipArchiveEntry motherentry { get; set; }  /Compressed file within the source file
        public string Name { get; set; }
        public string ActualBytes { get; set; }
        public string CompressedBytes { get; set; }
    }

    public List<ZipItem> results;      //List of all ZipItems (all elements of a Zipfile, for manipulation purposes)
    public int numfiles = 0;   // Total number of files 
    public int i = 0;   //Pointer to the current element in the list (for slideshow purposes)


    private async void  nextimg_Click(object sender, RoutedEventArgs e)
    {
        Stream stream = await results[i].motherfile.OpenStreamForReadAsync(); //Create a stream... I know this is the wrong type (see error below)

        ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Update);  //Open the ZipArchive. This gives me an error telling me that "Update mode requires a stream with Read, Write and Seek permission.

        ZipArchiveEntry entry = results[i].motherentry; //This is where I'm stuck.... how do I tell it to open a specific entry in the zip file?

        using (var fileStream = entry.Open()) //How do I open it as an IRandomAccessStream?
        //using (IRandomAccessStream fileStream = results[i].motherentry.Open());
        {

            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.DecodePixelHeight = (int)ctlImage.Height;
            bitmapImage.DecodePixelWidth = (int)ctlImage.Width;
            bitmapImage.SetSource(filestream); //I know I need a IRandomAccessStream
            ctlImage.Source = bitmapImage;   //Hopefully display the image... 

        }

    }
...