首页 > 其他分享 >【HarmonyOS NEXT应用开发】案例69:基于原生能力的压缩与解压缩能力

【HarmonyOS NEXT应用开发】案例69:基于原生能力的压缩与解压缩能力

时间:2024-08-24 11:27:27浏览次数:15  
标签:解压 fs 压缩 zlib 解压缩 NEXT HarmonyOS let zs

一、场景描述

概览、常用图片编码格式比对及系统支持情况

压缩格式

简介

系统支持/使用方式

zip

普及率高,适用范围也最广,压缩速度相比rar快一些

ArkTs支持,可通过zlib实现,jszip

rar

rar格式比zip更能够提供较好的压缩率,但压缩速度也相对慢一些

三方库支持,通过Unrar实现

7z

压缩率相对前两种最大,但速度也最慢

三方库支持,通过commons-compress实现

brotli

无损压缩算法,主要目标是压缩 Internet 上的数据

三方库支持,通过commons-compress实现

tar

简单封装,被称为归档文件,只是简单的将文件组装到一个.tar的文件内,并没有太多文件体积的减少,仅仅是简单的封装

三方库支持,通过commons-compress实现

gzip

.gz:使用gzip算法将文件压缩到一个文件,极大的减少压缩后的体积

三方库支持,通过三方库pako实现

ArkTs侧:

场景一:压缩与解压rawfile目录下的文件,由于在resource/rawfile目录下存放的文件,没有对外暴露的沙箱路径,无法使用文件管理接口或以沙箱路径形式处理,因此需要将rawfile下文件通过fs拷贝进沙箱目录下,再使用zlib进行压缩与解压。

场景二:压缩与解压resfile下的文件,通过getContext().resourceDir获取到该路径下的文件,再使用zlib进行压缩与解压。

Native侧:

当前鸿蒙暂无native的压缩与解压接口,本文主要介绍native侧通过zlib实现压缩与解压。

二、方案描述

ArkTs侧

方案

1)通过resourceManager.getRawFileContent获取到rawfile下的文件;

2)然后通过fs将rawfile文件内容copy到沙箱路径;

3)最后使用zlib.decompressFile对沙箱路径下的压缩文件进行解压。

效果图

cke_6374.png

核心代码

function resfileZlibDecompress() {

getContext().resourceManager.getRawFileContent('file1.zip', (_err, value) => {



//将rawfile下的文件拷贝至沙箱下,沙箱路径:/data/storage/el2/base/haps/entry/filesfile1.zip

let myBuffer: ArrayBufferLike = value.buffer

let filePath = getContext().filesDir + "file1.zip";

let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);

let writeLen = fs.writeSync(file.fd, myBuffer);

fs.closeSync(file);

let outFileDir = getContext().filesDir;

let options: zlib.Options = {

level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION

};



//解压沙箱下的文件

try {

zlib.decompressFile(filePath, outFileDir, options, (errData: BusinessError) => {

if (errData !== null) {

console.error(`errData is errCode:${errData.code} message:${errData.message}`);

}

})

} catch (errData) {

let code = (errData as BusinessError).code;

let message = (errData as BusinessError).message;

console.error(fs.accessSync(filePath)+`errData is errCode:${code} message:${message}`);

}

})

}

2.压缩rawfile目录下的文件

方案

思路同rawfile解压,用到的方法:resourceManager.getRawFileContent、fs、zlib.compressFile

核心代码

getContext().resourceManager.getRawFileContent('file1.txt', (_err, value) => {

let myBuffer: ArrayBufferLike = value.buffer

//将rawfile下的文件拷贝至沙箱下,沙箱路径:/data/storage/el2/base/haps/entry/files/file1.txt

let filePath = getContext().filesDir + "/file1.txt";

let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);

let writeLen = fs.writeSync(file.fd, myBuffer);

fs.closeSync(file);



//压缩沙箱下的文件

let outFile = getContext().filesDir + '/file1.zip';

let options: zlib.Options = {

level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION,

memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT,

strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY

};

zlib.compressFile(filePath, outFile, options)

})

方案

通过 getContext().resourceDir获取resfile目录下文件,再使用zlib.decompressFile对文件进行解压

效果图

核心代码

let inFile = getContext().resourceDir + '/file1.zip';

let outFile = getContext().filesDir;

let options: zlib.Options = {

level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION

};

//解压沙箱下的文件

zlib.decompressFile(inFile, outFile, options)

方案

思路同resfile解压,用到的方法:zlib.compressFile

核心代码

let inFile = getContext().resourceDir + '/file1.txt';

let outFile = getContext().filesDir + "/file1.zip";

let options: zlib.Options = {

level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION,

memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT,

strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY

};

//压缩沙箱下的文件

zlib.compressFile(inFile, outFile, options)

native侧

zlib库进行gzip压缩

当前ArkTs侧zlib暂不支持gzip压缩,可以使用基础库压缩,参考zlib Usage Example

方案

​ 1)首先初始化z_stream结构体,然后设置输入数据和输出buffer的信息。

​ 2)接着使用deflateInit2函数初始化,并使用deflate函数进行压缩。如果输出buffer不足以存储所有压缩数据,则进行拓容并重复压缩的过程,直到所有数据压缩完毕。

​ 3)最后,返回压缩后的数据和数据大小,并使用deflateEnd函数释放。

​ 头文件:zlib.h

核心代码

char* compressToGzip(const char *input, int inputSize, int* outputSize) {

z_stream zs;

// 初始化 (主要用于开发者自定义内存管理, 此处不使用, 应用有诉求可参考:https://www.zlib.net/manual.html)

zs.zalloc = Z_NULL; // 用于分配内部状态

zs.zfree = Z_NULL; // 用于释放内部状态

zs.opaque = Z_NULL; // 传递给 zalloc、zfree的私有数据对象



// 初始化输入数据

zs.next_in = (Bytef *)input; // 输入数据头

zs.avail_in = (uInt)inputSize; // 输入数据的内存块大小



// 初始化输出buffer

char *compressedData = new char[CHUNK_SIZE];

// 输出头

zs.next_out = (Bytef *)compressedData;

zs.avail_out = (uInt)CHUNK_SIZE;



// 开始压缩(此处使用空的gzip头)

int windowBits = WINDOWS_BITS; // windowBits历史缓冲区的大小,此参数的值越大,压缩效果越好。 范围(8-15)

// 特殊:windowBits加上 16,表示使用gzip头 windowBits加上 32,表示自动识别gzip/zlib头

int memLevel = 8; // memLevel=1使用最小内存但速度较慢,降低压缩比; memLevel=9使用最大内存以获得最佳速度 默认值为8



deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY);



// 压缩 尽量一次压缩完毕

deflate(&zs, Z_FINISH);



int chunkCount = 1; // 数据块的个数

// 重复压缩

while (zs.avail_out == 0) {

// 为输出数据 拓容

chunkCount++;

char* newBuffer = new char[CHUNK_SIZE*chunkCount];

// 复制历史数据

memcpy(newBuffer, compressedData, CHUNK_SIZE*(chunkCount-1));

delete[] compressedData;

compressedData = newBuffer;



// 继续压缩

zs.next_out = (Bytef *)(compressedData+CHUNK_SIZE*(chunkCount-1));

zs.avail_out = (uInt)CHUNK_SIZE;

deflate(&zs, Z_FINISH);

}

// 返回结果

*outputSize = zs.total_out;

deflateEnd(&zs);

return compressedData;

}

zlib库进行gzip解压

方案

思路与压缩相同,使用inflateInit2函数初始化zlib库,然后调用inflate进行解压缩,最后调用inflateEnd结束解压。

核心代码

char* decompressGzip(const char *input, int inputSize, int* outputSize) {

z_stream zs;

zs.zalloc = Z_NULL;

zs.zfree = Z_NULL;

zs.opaque = Z_NULL;

zs.avail_in = (uInt)inputSize;

zs.next_in = (Bytef *)input;

char *deCompressedData = new char[CHUNK_SIZE];

zs.avail_out = (uInt)CHUNK_SIZE;

zs.next_out = (Bytef *)deCompressedData;

inflateInit2(&zs, WINDOWS_BITS);

// 解压 尽量一次解压完毕

inflate(&zs, Z_FINISH);

int chunkCount = 1; // 数据块的个数

// 重复解压

while (zs.avail_out == 0) {

// 为输出数据 拓容

chunkCount++;

char* newBuffer = new char[CHUNK_SIZE*chunkCount];

// 复制历史数据

memcpy(newBuffer, deCompressedData, CHUNK_SIZE*(chunkCount-1));

delete[] deCompressedData;

deCompressedData = newBuffer;

// 继续压缩

zs.next_out = (Bytef *)(deCompressedData+CHUNK_SIZE*(chunkCount-1));

zs.avail_out = (uInt)CHUNK_SIZE;

inflate(&zs, Z_FINISH);

}

// 返回结果

*outputSize = zs.total_out;

inflateEnd(&zs);

return deCompressedData;

}

标签:解压,fs,压缩,zlib,解压缩,NEXT,HarmonyOS,let,zs
From: https://blog.csdn.net/xzs51job/article/details/141301288

相关文章

  • 栅格布局在 HarmonyOS 中的应用及扩展
    栅格布局作为一种经典的布局方式,广泛应用于不同类型的用户界面设计,尤其是在移动设备和响应式设计中,它表现出了强大的适应性。本文将深入探讨如何在HarmonyOS中使用栅格布局组件GridRow和GridCol,并通过多种示例来展示栅格布局的灵活性及扩展性。栅格布局的核心优势1.......
  • 深入解析HarmonyOS中的媒体查询及其高级用法
    在移动应用开发中,响应式设计是一个关键要素。HarmonyOS提供了一整套媒体查询功能,可以让开发者根据设备类型、屏幕尺寸、方向等条件动态调整应用的布局和样式。本文将深入探讨HarmonyOS中的媒体查询功能,展示其高级用法,帮助你构建更灵活的用户界面。媒体查询在HarmonyOS中的......
  • 【HarmonyOS NEXT星河版开发实战】天气查询APP
    目录前言界面效果展示首页添加和删除 界面构建讲解1.获取所需数据 2.在编译器中准备数据 3.index页面代码讲解 3.1导入模块: 3.2 定义组件:3.3 定义状态变量:3.4  定义Tabs控制器:3.5 定义按钮样式: 3.6 页面显示时触发的方法: 3.7 获取数据的方......
  • 【鸿蒙学习】HarmonyOS应用开发者高级认证 - 应用性能优化一(界面层面)
    学完时间:2024年8月22日学完排名:第1801名一、介绍在开发HarmonyOS应用时,优化应用性能是至关重要的。通过/ArkTS高性能编程、减少丢帧卡顿、提升应用启动和响应速度可以有效提升用户体验。本文将介绍一些优化HarmonyOS应用性能的方法。一、ArkUI框架执行流程在使用A......
  • 探索HarmonyOS中的列表组件及其自定义特性
    在现代移动应用中,List组件是数据列表的关键元素。HarmonyOS中的List组件不仅具备传统的列表功能,还提供了丰富的自定义选项,允许开发者根据需求灵活调整列表的行为和外观展示。本文将探讨HarmonyOS中列举组件的自定义特性,包括自定义项布局、动态加载数据、多列布局、拖拽排序......
  • nextjs 客户端图片 因跨域 strict-origin-when-cross-origin 无法展示
    使用next.config.js配置跨域规则Next.js提供了一个配置文件next.config.js,你可以在其中配置images选项,以允许跨域加载图片。在Next.js中,remotePatterns配置用于定义允许加载远程图像的域名及路径。不过,remotePatterns并不支持传统的正则表达式,而是使用类似正则表达式......
  • 「字符串」前缀函数|KMP匹配:规范化next数组 / LeetCode 28(C++)
    概述为什么大家总觉得KMP难?难的根本就不是这个算法本身。在互联网上你可以见到八十种KMP算法的next数组定义和模式串回滚策略,把一切都懂得特别混乱。很多时候初学者的难点根本不在于这个算法本身,而是它令人痛苦的百花齐放的定义。有的next数组从0下标开始,有的从1开始;有的表......
  • 【鸿蒙学习】HarmonyOS应用开发者高级认证 - 自由流转
    学完时间:2024年8月21日学完排名:第2253名一、基本概念1.流转在HarmonyOS中,将跨多设备的分布式操作统称为流转。流转能力打破设备界限,多设备联动,使用户应用程序可分可合、可流转,实现如邮件跨设备编辑、多设备协同健身、多屏游戏等分布式业务。流转为开发者提供更广的使......
  • 理解HarmonyOS中的Flex布局
    在开发HarmonyOS应用时,布局是一个至关重要的方面。布局不仅决定了应用的外观,也影响了用户的体验和交互方式。在HarmonyOS中,Flex布局是一种强大且灵活的布局方式,适用于创建复杂的界面结构。本文将带您深入了解Flex布局的核心概念以及如何在实际开发中有效利用它。什......
  • 鸿蒙Next-支付宝SDK接入教程
    App适配鸿蒙Next,开始做支付功能了,目前来说只有支付宝支持鸿蒙Next,微信还没上架,但是支付宝官方的文档跟Demo都很老,下载官方的Demo用最新版的DevEco-Studio导入都不成功。后面在OpenHarmony三方库中心仓找到了最新的代码:https://ohpm.openharmony.cn/#/cn/detail/@cashier_alipay......