我正在开发一个使用本地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,虽然有一些声称支持LZMA解压缩的C#库,但它们与我的Windows Phone项目不兼容(我认为由于已经为.NET3或.NET4设置了但是不是.NET3.5)。
我考虑过使用LZMA SDK实现ICSharpCode.SharpZipLib.LZMA类,但在我重新发明任何轮子之前,我想我应该问一下是否有人在Windows Phone上成功解压缩了LZMA拉链?
任何帮助都非常感激。
答案 0 :(得分:2)
我继续寻找LZMA解压缩的Windows Phone实现,但没有运气,所以我根据LZMA SDK版本9.22测试版制作了一个。在此处发布详细信息,以防有人发现它有用(当然不做任何保证)。
项目来源可以在这里找到: https://github.com/larryk78/SevenZip.Compression.LZMA.WindowsPhone/
该实现提供了三种解压缩方案(我还没有考虑压缩):
StreamDecoder
包装SevenZip.Compression.LZMA.Decoder
(来自SDK)并提供流到流的解压缩。IsolatedStorageDecoder
扩展StreamDecoder
以从IsolatedStorage中的流或文件解压缩到IsolatedStorage中的文件;即分别为流到文件和文件到文件。WebClient2IsolatedStorageDecoder
扩展IsolatedStorageDecoder
以从Uri
下载压缩文件,然后将其解压缩到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 :)
}
如果您尝试,请告诉我。没有什么比真实用户的反馈更好:)
干杯, 拉里
P.S。此库不处理* .zip文件。它适用于LZMA压缩文件,即* .lzma。您可以使用LZMA SDK中的lzma.exe(二进制文件也在上面链接的github存储库中)制作这些文件。我和ICSharpCode.SharpZipLib库的维护者聊了一下关于将LZMA集成到那里的问题,他很敏感所以让我们看看那里发生了什么......