第54篇|ZIP 压缩库适配 HarmonyOS
第54篇|ZIP 压缩库适配 HarmonyOS

图 1:ZIP压缩库适配封面图,用来概括本文主题、适配对象和工程边界。
压缩包适配不能只验证一个文件,目录层级、中文文件名和路径穿越都要处理。
本文围绕 压缩包 和 目录解压 展开,目标不是把库接进工程后截图结束,而是把来源、版本、配置、封装、运行和验收写成一条读者可以复现的链路。

图 2:ZIP压缩库适配流程图,用来说明从需求拆解、依赖接入、封装实现到回归验收的主要步骤。

图 3:ZIP压缩库适配结构图,用来说明配置层、适配层、服务层、页面层和排错记录之间的职责。
1. 这类库先解决哪个工程问题
ZIP压缩库适配不能从 API 名称开始讲,要先说清楚它解决什么工程问题。实际接入时,读者最关心的是库进入项目后由哪一层调用、失败以后看哪里、版本升级时哪些地方需要回归。
本文把问题收敛到 压缩包 的输入、目录解压 的执行和 entryCount 的验收指标。这样写的好处是范围明确,读者不会把选型、封装、页面和发布说明混成一团。
| 判断点 | 本文处理方式 | 读者落地时要替换的内容 |
|---|---|---|
| 输入来源 | 统一为 压缩包 | 替换成真实页面、文件或设备数据 |
| 核心动作 | 收敛到 目录解压 | 替换成三方库真实 API |
| 验收指标 | 使用 entryCount 做最小判断 | 替换成业务认可的结果字段 |
2. 源码和资料定位
适配前先建立源码地图。即使没有真实项目目录,也要把建议位置写清楚,让读者知道每段代码应该放在哪一层。
| 层级 | 建议文件 | 作用 |
|---|---|---|
| 依赖入口 | oh-package.json5 或 entry/src/main/cpp/CMakeLists.txt | 固定版本、源码或 Native 产物 |
| 适配层 | entry/src/main/ets/adapter/ZipArchiveAdapter.ets | 处理输入、错误和三方 API 差异 |
| 服务层 | entry/src/main/ets/service/ZipArchiveService.ets | 暴露业务可读方法 |
| 示例页面 | entry/src/main/ets/pages/ZipArchiveServicePage.ets | 提供可复现验收入口 |
| 验收记录 | docs/zip-archive-acceptance.md | 保存版本、命令和限制 |
3. 环境和版本边界
版本边界需要写在正文前半部分。HarmonyOS API、DevEco Studio、ohpm 包版本、Native ABI、设备能力都会影响结果,不能默认读者的环境和作者一致。
| 环境项 | 示例值 | 检查重点 |
|---|---|---|
| HarmonyOS API | API 12+ 或项目实际版本 | 系统能力、权限和组件行为 |
| 开发工具 | DevEco Studio 5.x | 构建、预览和签名流程 |
| 依赖形式 | ArkTS 包 / Native so / 源码模块 | 决定排查入口 |
| 目标设备 | 模拟器或真机 | 多媒体、蓝牙、相机等能力要真机确认 |
| 回归入口 | 示例页 + 命令行 | 能重复触发核心能力 |
4. 配置入口先收口
配置层只负责让依赖进入工程,不要混入业务判断。包管理类库固定版本,Native 类库固定 include、lib 和 ABI,涉及权限的库还要补模块声明。
{
"name": "zip-archive-sample",
"version": "1.0.0",
"dependencies": {
"@demo/zip-archive": "1.0.0"
},
"metadata": {
"verifiedApi": "API 12+",
"entry": "ZipArchiveService"
}
}
这段配置的边界是“可追踪”。它让读者知道依赖从哪里来、版本是什么、入口服务是哪一个。真正的业务规则放到服务层,不放在配置里。
5. 适配层负责输入和错误
适配层不要只包一层同名方法。它要处理空输入、格式归一化、错误转换和返回结构。这样页面拿到的结果才稳定。
export interface ZipArchiveServiceResult {
ok: boolean;
message: string;
entryCount: number;
}
export class ZipArchiveAdapter {
normalize(raw: string): string {
const value = raw.trim();
if (value.length === 0) {
throw new Error('压缩包不能为空');
}
return value;
}
execute(raw: string): ZipArchiveServiceResult {
const value = this.normalize(raw);
return {
ok: true,
message: '目录解压完成: ' + value,
entryCount: value.length
};
}
}
这段代码保护的是业务边界。三方库可以变化,但页面和上层服务只依赖 ZipArchiveServiceResult,不会被底层参数结构拖着改。
6. 服务层承接业务语义
服务层要把适配层结果变成业务能直接消费的状态。它可以记录来源、补默认值、控制重试,但不要把页面状态和三方库细节混在一起。
import { ZipArchiveAdapter, ZipArchiveServiceResult } from '../adapter/ZipArchiveAdapter';
export class ZipArchiveService {
private adapter = new ZipArchiveAdapter();
run(raw: string): ZipArchiveServiceResult {
try {
return this.adapter.execute(raw);
} catch (err) {
return {
ok: false,
message: (err as Error).message,
entryCount: 0
};
}
}
}
服务层的输入来自页面或业务流程,输出用于展示、缓存或提交。后续替换三方库时,只要服务层契约稳定,业务调用方就不用大面积改动。
7. 页面验收入口要可重复
示例页是文章可信度的一部分。读者需要看到输入、按钮、结果和异常信息如何串起来,而不是只看到一段孤立代码。
import { ZipArchiveService } from '../service/ZipArchiveService';
@Entry
@Component
struct ZipArchiveServicePage {
@State input: string = 'zip-archive-input';
@State output: string = '等待运行';
private service = new ZipArchiveService();
build() {
Column({ space: 12 }) {
TextInput({ text: this.input, placeholder: '输入压缩包' })
.onChange((value: string) => this.input = value)
Button('执行目录解压')
.onClick(() => {
const result = this.service.run(this.input);
this.output = `${result.ok} / ${result.message} / entryCount=${result.entryCount}`;
})
Text(this.output).fontSize(14)
}
.padding(20)
}
}
页面验收要覆盖正常输入和空输入。空输入能否被明确提示,能直接反映适配层是否真正承担了边界保护。
8. Native 或底层调用边界
如果库有 Native、SDK 或系统能力调用,需要再单独写一层底层包装。底层包装只负责调用 extractArchive、转换结果和释放资源,不承担页面逻辑。
#include <string>
struct NativeResult {
bool ok;
int value;
std::string message;
};
NativeResult RunZipArchiveService(const std::string &input)
{
if (input.empty()) {
return { false, 0, "empty input" };
}
int value = static_cast<int>(input.size());
return { true, value, "extractArchive completed" };
}
这段代码的重点是边界清晰。Native 层不直接返回裸指针、不让页面处理错误码、不把资源释放交给调用方猜测。
9. 命令行验证要给读者路径
文章里的命令不需要多,但要能帮读者定位问题。包管理、构建产物、运行日志是三类最常用证据。
ohpm list --all
hvigorw --mode module -p module=entry assembleHap
hdc hilog | findstr zip_archive
执行后建议记录三项结果:依赖版本是否符合预期、HAP 是否能构建、示例页触发时是否有明确日志。这样后续换版本时可以直接对比。
10. 常见问题排查
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
| 页面没有结果 | 服务层吞掉错误或没有刷新状态 | 返回 ok/message 并展示到示例页 |
| 构建失败 | 版本、路径或 ABI 不一致 | 回到依赖入口核对实际产物 |
| 真机异常 | 权限、沙盒或设备能力不同 | 用真机日志确认失败位置 |
| 升级后行为变化 | 三方库默认参数变化 | 保留示例页作为回归入口 |
排查顺序固定为配置、构建、适配层、页面层。这个顺序能避免一开始就改 UI,最后才发现是依赖版本错了。
11. 验收断言
验收断言把“能看见效果”变成“结果满足契约”。下面的断言可以放在 smoke 流程里,也可以在示例页触发后手动核对。
export function assertZipArchiveServiceReady(result: ZipArchiveServiceResult): void {
if (!result.ok) {
throw new Error(`ZIP压缩库适配执行失败: ${result.message}`);
}
if (result.entryCount <= 0) {
throw new Error(`entryCount 不符合预期: ${result.entryCount}`);
}
}
这段断言的价值在升级时更明显。只要返回结构或关键指标变了,问题会在验收阶段暴露,而不是等到业务页面上线后才发现。
12. 完成前清单
- 依赖来源、版本和许可证已记录。
- 配置入口、适配层、服务层和页面层职责分开。
- 示例页能重复触发
目录解压。 - 空输入、异常输入和正常输入都有明确结果。
- 命令行验证能定位依赖、构建和日志。
- 常见问题表能覆盖读者最可能遇到的失败。
- 图片、图注和结构说明能帮助读者复现。
这份清单建议每次升级库版本后重新执行。尤其是涉及 压缩包 和 目录解压 的场景,不能只看构建是否成功,还要确认页面状态、日志输出和错误兜底都保持一致。
13. 小结
ZIP压缩库适配的适配重点是把库能力变成项目可维护能力。源码、配置、封装、页面、命令和验收都写清楚,读者才能把文章内容迁移到自己的工程里,而不是只得到一个无法复现的示例。
参考资料
参考资料用于核对 API、平台能力和构建链路。正式接入前,应结合当前 SDK、三方库 README、Release 记录和项目权限配置重新确认边界。
更多推荐



所有评论(0)