2012-03-04 113 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整合進去,他非常熱衷於讓我們看看會發生什麼......