
示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载本篇指南围绕 Windows-universal-samples 仓库中归档的 Compression数据压缩/解压缩JavaScript 示例展开先完整继承该示例 README 中的功能清单、算法说明与操作系统要求再结合仓库内 js/ 目录下的真实源码逐步剖析批量文件压缩/解压缩与结构化对象压缩/解压缩两条完整链路最终给出可复现的构建、部署与运行步骤。读完本文你将理解Windows.Storage.Compression托管接口的封装方式、四种压缩算法的取舍以及示例中WinJS.Compressor/WinJS.Decompressor包装类的实现细节。示例功能总览该示例的目标README 原文表述是演示如何从文件读取结构化数据并将压缩后的数据写入新文件以及如何读取压缩数据并将解压后的数据写入新文件。README 中列出的具体能力清单如下后文的源码分析将逐条对应从已有文件读取未压缩数据指定要使用的压缩算法使用所选压缩算法压缩数据将压缩后的数据写入新文件从文件读取压缩数据解压缩数据。示例以两个场景页面的形式组织见 sample-configuration.js 中的场景注册JavaScript 对象压缩/解压缩object.html将 JavaScript 对象序列化并压缩到内存流再从内存流解压缩并反序列化验证往返一致性批量流压缩/解压缩stream.html通过文件选择器选择任意文件压缩到应用临时目录中的新文件再解压到另一个新文件。说明本示例是 UWP 功能示例合集的一部分。README 提示若以 ZIP 方式获取整个示例合集务必解压全部内容而不仅解压单个示例文件夹否则无法访问各示例共享的依赖。该示例位于仓库的archived/归档目录下属于已归档的历史 JavaScript/WinJS 版本。Windows.Storage.Compression统一的托管压缩接口README 对该 API 的定位值得单独强调许多应用都需要压缩与解压缩数据Windows.Storage.Compression命名空间提供了一个统一接口暴露MSZIP、XPRESS、XPRESS_HUFF 和 LZMS四种压缩算法。其价值在于屏蔽底层细节该命名空间承担了版本管理、服务维护和算法扩展的职责开发者无需操心块大小block size、压缩参数等原生 [Compression API] 所要求的细节与原生 API 的关系对于 WinRT 尚未覆盖的场景应用也可以走原生 Compression API 路线——README 指出Win32/COM 的部分能力正是为此目的保留给 UWP 应用的。示例正是建立在这套托管接口之上的压缩侧使用Windows.Storage.Compression.Compressor解压侧使用Windows.Storage.Compression.Decompressor两者都工作在流Stream抽象之上。操作系统要求README 给出的平台前提如下平台最低要求客户端Windows 10服务器Windows Server 2012 R2手机Windows 10 Mobile仓库中的 Package.appxmanifest 与此一致包标识为Microsoft.SDKSamples.Compression.JS目标设备族Windows.Universal的MinVersion10.0.10240.0即 Windows 10 首发版本、MaxVersionTested10.0.18362.0。项目结构与入口归档后的 Compression 示例只保留了 JavaScriptWinJS语言版本位于 archived/Compression/js/核心文件如下文件职责Compression.sln / Compression.jsproj解决方案与项目文件Visual Studio 打开入口Package.appxmanifest应用清单包名、版本、Universal 10.0.10240 目标js/sample-configuration.js注册两个演示场景及其标题js/compression.js自定义的WinJS.Compressor/WinJS.Decompressor包装类全示例的核心js/stream.js批量流压缩/解压缩场景逻辑js/object.js结构化对象压缩/解压缩场景逻辑html/stream.html / html/object.html两个场景的 UI含 5 个算法选择按钮压缩算法选择README 与 UI 中的说明stream.html 与 object.html 各自提供 5 个按钮DEFAULT (XPRESS)、XPRESS、XPRESSHUFF、MSZIP、LZMS页面上同时给出了官方的算法特性描述README 提到的四种算法中DEFAULT 与 XPRESS 实际同为 XpressDEFAULT不显式指定压缩算法默认使用 XpressXPRESS压缩比一般但压缩与解压缩速度最快内存占用低MSZIP压缩比高压缩速度中等、解压缩速度快内存占用低XPRESSHUFF / LZMS按钮存在对应CompressAlgorithm.xpresshuff与CompressAlgorithm.lzms两个枚举成员LZMS 面向高压缩比场景。场景代码中按钮点击事件通过统一工厂函数绑定见 stream.jsfunction scenario(algorithm) { return function () { clearProgress(); if (typeof (algorithm) undefined) { doScenario(); // 使用默认算法 } else { doScenario(Windows.Storage.Compression.CompressAlgorithm[algorithm]); } }; } document.getElementById(DefaultButton).addEventListener(click, scenario(), false); document.getElementById(XpressButton).addEventListener(click, scenario(xpress), false); document.getElementById(XpressHuffButton).addEventListener(click, scenario(xpresshuff), false); document.getElementById(MszipButton).addEventListener(click, scenario(mszip), false); document.getElementById(LzmsButton).addEventListener(click, scenario(lzms), false);可以看到算法名以字符串形式如xpress按枚举成员名反射取值为CompressAlgorithm枚举再传入场景函数。场景一批量文件的压缩与解压缩stream.js该场景对应 README 中从文件读取数据 → 压缩 → 写入新文件 → 读取压缩文件 → 解压 → 写入新文件的完整链路实现在 stream.js 的doScenario函数中主流程如下文件选择创建FileOpenPickerfileTypeFilter.append(*)允许任意类型调用pickSingleFileAsync()。注意源码注释用户取消选择时该 Promise 会以null成功完成因此必须显式判空并抛出 No file has been selected。var filePicker new Windows.Storage.Pickers.FileOpenPicker; filePicker.fileTypeFilter.append(*); filePicker.pickSingleFileAsync().then(function (file) { if (file null) { throw No file has been selected; } // ... 压缩/解压缩流程 }, onError);构造压缩器输出文件名采用原文件名.算法名.compressed的命名约定解压缩输出为原文件名.算法名.decompressed。当不指定算法时源码注释明确推荐只传文件名、不传算法的初始化方式默认 Xpressvar compressedFileName file.name . algorithmName .compressed; var decompressedFileName file.name . algorithmName .decompressed; if (typeof (compressAlgorithm) undefined) { // 无特定算法要求时这是推荐的 Compressor 初始化方式 compressor new WinJS.Compressor(compressedFileName); } else { compressor new WinJS.Compressor(compressedFileName, compressAlgorithm); }压缩直接把IStorageFile传给compressAsync包装类内部会处理文件到流的转换完成后调用close()释放资源解压缩这里有一个容易踩的坑——源码注释指出不能直接用compressedFileName因为系统可能为了避免命名冲突自动重命名文件必须使用compressor.fileName属性取回真实文件名compressor.compressAsync(file).then(function () { showProgress(Compression done); compressor.close(); var decompressor new WinJS.Decompressor(compressor.fileName); // 注意用实际文件名 return decompressor.copyAsync(decompressedFileName).then(function () { showProgress(Decompression done); decompressor.close(); }, onError); }, onError);Picker 续接File Picker Continuation支持stream.js 还实现了WinJS.Application.onactivated中的pickFileContinuation分支——当应用通过文件选择器续接方式被激活时从args.detail.continuationData[algorithmName]取出算法名、从args.detail.files[0]取出文件直接走compressFile流程。这使得示例既可独立运行也能作为其他应用的压缩续接目标。场景二结构化对象压缩与解压缩object.js该场景演示 README 所说的读取结构化数据并压缩/解压缩核心实现在 object.js 的doScenario中构造测试对象var testObject [1, 2, 3, sampletext, { value: sampleobject }];源码注释特别说明这个小对象仅用于演示目的。真实世界中的此类小对象熵entropy不足压缩收益会被格式元数据抵消实际不值得压缩。内存流上的读写分离这里有一个关键的流模型细节。InMemoryRandomAccessStream查询出的IInputStream与IOutputStream共享同一个读写位置因此必须先压缩、后解压且要么在读取前回绕rewind流要么用getOutputStreamAt/getInputStreamAt获取相互独立的流视图var stream new Windows.Storage.Streams.InMemoryRandomAccessStream(); var compressor new WinJS.Compressor(stream.getOutputStreamAt(0), compressAlgorithm); var decompressor new WinJS.Decompressor(stream.getInputStreamAt(0));压缩、解压缩与往返校验compressAsync(testObject)会把对象JSON.stringify后写入压缩器readObjectAsync()解出字符串再JSON.parse还原对象最后用JSON.stringify双向序列化对比验证压缩—解压缩往返的保真性compressor.compressAsync(testObject).then(function () { compressor.close(); return decompressor.readObjectAsync(); }).then(function (decompressedObject) { decompressor.close(); if (JSON.stringify(testObject) JSON.stringify(decompressedObject)) { showProgress(Test object matches decompressed one); } else { onError(new Error(Test object doesnt match decompressed one)); } }, onError);包装类实现剖析WinJS.Compressor 与 WinJS.Decompressor示例的精髓在 compression.js它用WinJS.Class.define定义了两个对 Windows API 的 Promise 化包装类展示了如何在 JS 中组织 WinRT 异步调用的典型模式。底层流的鸭子类型解析构造函数接收的underlyingStream可以是三种形态之一getUnderlyingStreamPromise用鸭子类型duck typing逐一识别compression.js输入形态识别依据处理方式流所有权文件名字符串typeof string在ApplicationData.current.temporaryFolder中createFileAsync冲突策略replaceExisting再以readWrite模式打开包装类拥有该流close()时关闭IOutputStream/IInputStream存在writeAsync/readAsync函数直接透传不拥有该流close()时不关闭IStorageFile存在openAsync函数openAsync打开后使用拥有打开得到的流注释中还坦承了鸭子类型的风险WinRT 对象无法做接口检查若假阳性匹配错误会在底层实现深处才暴露但因调用方总是知道自己创建的对象类型这种概率很低。Compressor默认算法与默认块大小构造器中compression.jsfunction (underlyingStream, compressAlgorithm) { this._underlyingStreamPromise getUnderlyingStreamPromise(underlyingStream, this); this._compressAlgorithm compressAlgorithm ? compressAlgorithm : Windows.Storage.Compression.CompressAlgorithm.xpress; }不传算法时回落到CompressAlgorithm.xpress与 UI 上 DEFAULT (XPRESS) 的说明一致。compressAsync(data)内部创建真正的压缩器时compression.jsvar compressor new Windows.Storage.Compression.Compressor(underlyingStream, that._compressAlgorithm, /* use default block size */0); var writer new Windows.Storage.Streams.DataWriter(compressor);第三参0表示使用默认块大小——这正是 README 所说的托管接口替你管理块大小等细节的具体落点。收尾流程是标准的三步finishAsync()冲刷压缩缓冲 →detachStream()断开底层流 →close()释放 COM 对象最后再对底层流执行flushAsync()。compressAsync对输入数据同样做了鸭子类型分派IInputStream走RandomAccessStream.copyAsync流拷贝IStorageFile先openAsync(read)再拷贝字符串直接writeString普通对象先JSON.stringify再写入。fileName 属性与自动重命名fileName只在压缩器基于文件名字符串或IStorageFile创建时有效且源码注释提醒实际文件名可能与传入值不同——例如已存在filename.ext时再创建同名文件系统会重命名为filename (2).ext。这就是 stream.js 中坚持使用compressor.fileName的原因。Decompressor分块读取与 copyAsyncreadStringAsync()基于DataReader以16384 字节为一块循环loadAsync读到的 0 字节即到达结尾随后detachStreamclosecompression.jsreadObjectAsync(reviver)在其上叠加JSON.parsecopyAsync(destinationStream)支持三种目的地文件名字符串 /IOutputStream/IStorageFile统一经RandomAccessStream.copyAsync完成流对流的解压拷贝收尾时若有自管理的流则先flushAsync再close两个类的close()都遵循同一所有权约定只关闭自己打开的流_ownedStream透传进去的外部流不关闭并将_underlyingStreamPromise置空之后任何操作都会以 Object has already been closed 报错防止对已释放对象的误用。构建、部署与运行以下构建步骤完整继承自 README工具链前提为 Microsoft Visual Studio 2017本归档版本在仓库中的实际入口为 archived/Compression/js/Compression.sln构建示例若通过 ZIP 下载示例合集务必解压整个归档而不仅是目标示例所在的文件夹启动 Visual Studio 2017选择FileOpenProject/Solution在解压目录中找到本示例所在文件夹归档版本位于archived/Compression/js/及其语言子文件夹双击其中的解决方案文件Compression.sln按CtrlShiftB或选择BuildBuild Solution。仅部署示例在Solution Explorer中选择Compression使用BuildDeploy Solution或BuildDeploy Compression。部署并运行示例在Solution Explorer中右键Compression选择Set as StartUp Project调试并运行按 F5 或使用DebugStart Debugging不调试直接运行按 CtrlF5 或使用DebugStart Without Debugging。运行后的应用会展示sample-configuration.js注册的SdkSample场景框架标题为 Data Compression / Decompression SDK Sample左侧列出上述两个场景点击按钮即触发对应算法的完整压缩/解压缩演示并在页面下方的scenarioProgress区域输出 Testing... / Compression done / Decompression done / Test finished 等进度文本。小结与实操要点结合 README 与仓库源码该示例给出的可复用经验可归纳为优先使用Windows.Storage.Compression托管接口算法MSZIP / XPRESS / XPRESS_HUFF / LZMS的统一选择、默认算法回落Xpress、默认块大小块大小参数传 0都由运行时接管仅在需要原生 Compression API 级别的细节控制时才下沉到原生接口算法取舍看场景追求速度选 XPRESS默认追求压缩比选 MSZIP更高压缩比场景可评估 LZMS / XPRESSHUFF小数据量如演示用的小对象压缩收益可能低于元数据开销选型时应以真实数据规模为准注意 WinRT 流的所有权与位置语义透传流不应由包装类关闭IRandomAccessStream的输入/输出流共享位置需回绕或用getInputStreamAt/getOutputStreamAt基于文件名创建输出文件时务必以compressor.fileName为准因为系统自动重命名会使预设文件名失效本示例已归档于仓库archived/目录属于 JavaScript/WinJS 技术栈的历史实现其 API 用法Windows.Storage.Compression的Compressor/Decompressor、块大小、算法枚举在当前 Windows 10/11 UWP 与 WinRT 应用中依然有效可直接迁移到 C# 或 C/WinRT 工程中使用。赞分享示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载相关推荐Path of Building流放之路玩家的终极角色构建神器Path of Building流放之路玩家的终极角色构建神器 Path of Building是一款专为《流放之路》玩家设计的离线角色构建规划工具能够帮助桌面应用UWP 中 ListView 与 GridView 的实战指南基于 Windows-universal-samples XamlListView 示例的源码解析UWP 中 ListView 与 GridView 的实战指南基于 Windows universal samples XamlListView 示例的源码解示例工程Google App Engine Boilerplate性能优化指南提升Legacy应用响应速度的7个技巧Google App Engine Boilerplate性能优化指南提升Legacy应用响应速度的7个技巧 Google App Engine Boiler上一篇Bilibili-Evolved资源优先级加载preload与prefetch下一篇WinUtil3分钟搞定Windows系统优化与软件部署的终极方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考