2012-03-04 89 views
1

我正在开发使用本地SQLite数据库的Windows Phone 7项目。该数据库大约40MB未压缩,所以我使用最大压缩(Deflate)将其压缩到〜20MB。这是我的代码(工作)。如何在Windows Phone 7上解压缩LZMA压缩的zip文件?


    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内容。

我试过另一个库,但虽然它对于压缩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,虽然有其声称支持LZMA压缩一些C#库,他们没有与我的Windows Phone项目兼容的(我认为由于已经建立了.NET3或。 NET4但不是.NET3.5)。

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

任何帮助非常感谢。

回答

1

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

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

的实施提供了三种压缩的情况(我没有看压缩,尚):

  1. StreamDecoder包装SevenZip.Compression.LZMA.Decoder(从SDK)和提供流到流的解压缩。
  2. IsolatedStorageDecoderStreamDecoder扩展为从IsolatedStorage中的流或文件解压缩到IsolatedStorage中的文件;即流到文件和文件到文件。
  3. WebClient2IsolatedStorageDecoder延伸IsolatedStorageDecoderUri下载压缩文件,然后将其解压缩到IsolatedStorage中的文件。

N.B. 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整合进去,他非常热衷于让我们看看会发生什么......