1

ローカル 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: Compression method not supported)。


    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 を正常に解凍したかどうか尋ねるべきだと思いましたか?

どんな助けでも大歓迎です。

4

1 に答える 1

2

LZMA 解凍の Windows Phone 実装を探し続けましたが、運がなかったので、LZMA SDK バージョン 9.22 ベータに基づいて作成しました。誰かが役に立つと思った場合に備えて、ここに詳細を投稿します (もちろん、保証はありません)。

プロジェクトのソースはこちらにあります: https://github.com/larryk78/SevenZip.Compression.LZMA.WindowsPhone/

この実装では、3 つの解凍シナリオが提供されます (圧縮についてはまだ見ていません)。

  1. StreamDecoder(SDK から)ラップSevenZip.Compression.LZMA.Decoderし、ストリームからストリームへの圧縮解除を提供します。
  2. IsolatedStorageDecoderStreamDecoderストリームまたは IsolatedStorage 内のファイルから、IsolatedStorage 内のファイルへの解凍に拡張されます。つまり、それぞれストリームからファイルへ、ファイルからファイルへ。
  3. WebClient2IsolatedStorageDecoderIsolatedStorageDecoderから圧縮ファイルをダウンロードし、 IsolatedStorageUri内のファイルに解凍します。

NBStreamDecoderは として実装されている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 :)
}

試したら教えてください。Real User™ フィードバックに勝るものはありません :)

乾杯、ラリー

PS このライブラリは *.zip ファイルを処理しません。LZMA 圧縮ファイル、つまり *.lzma で動作します。これらは、LZMA SDK の lzma.exe を使用して作成できます (バイナリは、上記のリンク先の github リポジトリにもあります)。ICSharpCode.SharpZipLib ライブラリの管理者と LZMA の統合について話しましたが、彼は熱心なのでそこで何が起こるか見てみましょう...

于 2012-04-10T13:10:02.350 に答える