将 zip 文件的内容作为 StorageFile 对象读取而不提取?

Posted

技术标签:

【中文标题】将 zip 文件的内容作为 StorageFile 对象读取而不提取?【英文标题】:Read the content of a zip file as a StorageFile object without extracting? 【发布时间】:2019-02-10 00:53:08 【问题描述】:

仍在处理我的幻灯片项目!不太简陋,它现在可以递归读取目录,按顺序或随机顺序显示文件,放大和缩小,响应键盘和鼠标输入。

我现在正在尝试让它读取 zip 文件的内容而不提取它。当我递归读取用户提供的根目录作为输入时,它将遇到的所有文件存储为 StorageFile 对象的列表。我希望能够读取 zip 文件的内容并将其文件(即图像)添加到 StorageFile 列表中,然后最终打开并提取单个给定文件(如果它是按顺序或随机顺序排列的下一个文件)。

到目前为止,我发现允许提取磁盘上的文件或读取 zip 文件的内容作为字符串列表。

我清楚我需要什么吗?知道怎么做吗?

谢谢! :)

【问题讨论】:

您遇到了哪些问题?到目前为止你尝试了什么 我正在寻找一个类,它将为我提供从 zip 文件中读取而不提取它的功能,并将 zip 内容的每个元素作为 StorageFile 读取。不知何故,我能找到的所有东西,包括 ZipArchive 类都允许读取存档中的文件列表并提取其中一个。出于空间和性能原因,我不想提取文件,只是将其作为流读取。 哦!知道了! ZipArchiveEntry.Open 方法!一旦它工作,将发布代码示例! 现在怎么样了? 不好!哈哈!我花了一整天的时间摆弄这个没有成功。甚至 MS 自己的代码也不起作用(请注意,它们中经常有语法错误......)。现在我正在努力解决另一个问题,但很快就会回来并发布代码示例(不起作用......)。感谢您的提问! 【参考方案1】:

好的,我已经打开了 zip 文件,读取了它们的 ZipArchiveEntry 内容并在 ZipArchiveEntries 的内存中创建了一个列表。然而,我被困在两件事上:

1) 如何重新打开 ZipArchive 并访问我列表中的特定 ZipArchiveEntry?

2) 如何将 .jpg 图像的 ZipArchiveEntry 读入 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... 

        

    

【讨论】:

【参考方案2】:

好的……明白了!

首先,要读取特定条目,使用 ZipArchiveEntry.GetEntry(entrytosearch);

其次,无法将 ZipArchiveEntry 读入 IRandomAccessStream,我不知道为什么......在决定先在内存中读取它之前,它摆弄了一段时间。由于我正在做的是读取图像以显示在屏幕上,因此它对内存管理的影响有限。但是,如果您正在阅读大文章,请注意尺寸。在阅读之前,我会检查条目的 .Length 。但是,为了简单起见,这里是更新的代码,用于将 zip 文件的特定“.jpg”条目读取到 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;
        
    

【讨论】:

以上是关于将 zip 文件的内容作为 StorageFile 对象读取而不提取?的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一种方法访问 StorageFile

无法将类型 IAsyncOperation<StorageFile> 隐式转换为 StorageFile

另一个进程错误正在使用 UWP StorageFile 文件

你可以从它的路径访问一个选择的 StorageFile 吗? - UWP

如何保存StorageFile以便以后使用?

使用 python 将二进制数据写入 zip 文件