【问题标题】:How to unzip an LZMA compressed zip file on Windows Phone 7?如何在 Windows Phone 7 上解压缩 LZMA 压缩的 zip 文件?
【发布时间】:2012-03-22 03:20:01
【问题描述】:

我正在开发一个使用本地 SQLite 数据库的 Windows Phone 7 项目。该数据库未压缩约 40MB,因此我使用最大压缩(Deflate)将其压缩到约 20MB。这是我的代码(工作)。


    private void unzip_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = (BackgroundWorker)sender;
        IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
        IsolatedStorageFileStream file = new IsolatedStorageFileStream(filename, FileMode.Create, store);
        // TODO: switch from Deflate ~18.7MB to LZMA ~12.1MB (original ~41.5MB)
        StreamResourceInfo zipInfo = new StreamResourceInfo((Stream)e.Argument, null);
        StreamResourceInfo streamInfo = Application.GetResourceStream(zipInfo, new Uri(filename, UriKind.Relative));
        long total = streamInfo.Stream.Length;
        long done = 0;
        int size = 32768;
        byte[] data = new byte[size];
        while ((size = streamInfo.Stream.Read(data, 0, data.Length)) > 0)
        {
            file.Write(data, 0, size);
            done += size;
            int percentComplete = (int)(100 * ((float)done / (float)total));
            worker.ReportProgress(percentComplete);
        }
        file.Close();
    }

20MB 是一个很好的改进,但我注意到使用最大压缩 (LZMA) 的 7z 存档文件大小约为 12MB。 zip 文件格式支持 LZMA 内容,因此我将 Deflate 压缩 zip 文件切换为 LZMA 压缩 zip 文件和 bang。我得到 NullReferenceException:Application.GetResourceStream(...) 正在返回 null。大概该实现不处理 LZMA 内容。

我尝试了另一个库,但虽然它适用于 Deflated zip,但它在 LZMA zip 上再次失败(NotSupportedException:不支持压缩方法)。


    using ICSharpCode.SharpZipLib.Zip;
    ...
    private void unzip_DoWork(object sender, DoWorkEventArgs e)
    {
    ...
        using (ZipInputStream zip = new ZipInputStream((Stream)e.Argument))
        {
            ZipEntry entry = zip.GetNextEntry(); // consume zip header (required)
            ....
        }
    }

我查看了 NuGet,虽然有一些 C# 库声称支持 LZMA 解压缩,但它们与我的 Windows Phone 项目不兼容(我认为是因为已为 .NET3 或 .NET4 而不是 . NET3.5)。

我曾想过使用 LZMA SDK 实现一个 ICSharpCode.SharpZipLib.LZMA 类,但在我重新发明任何轮子之前,我想我应该问一下是否有人在 Windows Phone 上成功解压缩了 LZMA zip?

非常感谢任何帮助。

【问题讨论】:

    标签: windows-phone-7 deflate zipfile compression lzma


    【解决方案1】:

    我继续寻找 LZMA 解压缩的 Windows Phone 实现,但没有成功,所以我基于 LZMA SDK 版本 9.22 beta 制作了一个。在这里发布详细信息,以防任何人发现它有用(当然没有保证)。

    项目来源可以在这里找到: https://github.com/larryk78/SevenZip.Compression.LZMA.WindowsPhone/

    该实现提供了三种解压缩方案(我还没有研究压缩):

    1. StreamDecoder 包装 SevenZip.Compression.LZMA.Decoder(来自 SDK)并提供流到流的解压缩。
    2. IsolatedStorageDecoder 扩展StreamDecoder 以从IsolatedStorage 中的流或文件解压缩到IsolatedStorage 中的文件;即流到文件和文件到文件。
    3. WebClient2IsolatedStorageDecoder 扩展IsolatedStorageDecoder 以从Uri 下载压缩文件,然后将其解压缩到IsolatedStorage 中的文件。

    注意StreamDecoder 被实现为 BackgroundWorker,因此解压工作是异步完成的(不会阻塞 UI 线程),并且进度可以连接到 ProgressBar。

    这是一个使用WebClient2IsolatedStorageDecoder的例子:

    using SevenZip.Compression.LZMA.WindowsPhone;
    using System.ComponentModel;
    
    // <Button Content="Click Me!" Click="button_Click" />
    private void button_Click(object sender, RoutedEventArgs e)
    {
        WebClient2IsolatedStorageDecoder decoder = new WebClient2IsolatedStorageDecoder();
        decoder.ProgressChanged += new ProgressChangedEventHandler(decoder_ProgressChanged);
        decoder.RunWorkerCompleted += new RunWorkerCompletedEventHandler(decoder_RunWorkerCompleted);
        decoder.DecodeAsync(new Uri("http://example.com/compressed_file.lzma"), "decompressed_file.txt");
    }
    
    void decoder_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // <ProgressBar x:Name="Progress" />
        Progress.Value = e.ProgressPercentage;
    }
    
    void decoder_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error)
        {
            MessageBox.Show("Couldn't download/decompress: " + e.Error.Message);
            return;
        }
    
        // ...do something with the decompressed data :)
    }
    

    如果您尝试,请告诉我。没有什么能比得上真正的用户™ 反馈了 :)

    干杯, 拉里

    附:这个库不处理 *.zip 文件。它适用于 LZMA 压缩文件,即 *.lzma。您可以使用 LZMA SDK 中的 lzma.exe 制作这些文件(二进制文件也在 github 存储库中,上面链接)。我与 ICSharpCode.SharpZipLib 库的维护者聊过关于将 LZMA 集成到其中的问题,他很感兴趣,所以让我们看看那里发生了什么......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多