
回复
对于移动开发来说,原生的解压缩SDK往往满足不了用户的需求,比如鸿蒙的@ohos.zlib (Zip模块)就只支持zip格式的压缩包,也不支持获取压缩包内部列表和不解压获取压缩包的单个文件。
开发鸿蒙的解压缩功能,我们有三种方式:
1.使用原生@ohos.zlib (Zip模块)
2.使用OpenHarmony三方库jsZIP
3.使用native的三方库libarchive库开发。
还是先讲讲比较简单的开放方式——原生@ohos.zlib (Zip模块)
在应用沙箱目录下创建一个测试文件data.txt,并写入测试数据。示例代码如下。(app操作文件只能在沙箱里面操作)
import { fileIo as fs} from '@kit.CoreFileKit';
import { BusinessError, zlib } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State dataSize: number = 0;
build() {
Row() {
Column() {
// 在应用沙箱目录下创建文件data.txt,并写入测试数据
Button('创建测试文件data.txt').onClick(() => {
let path = getContext(this).filesDir;
// 创建文件data.txt
let inFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 写入测试数据
for (let index = 0; index < 100; index++) {
fs.writeSync(inFile.fd, index + ': hello world, hello world, hello world, hello world, hello world.\n');
}
// 获取测试数据原始大小,并保存到dataSize中
let stat = fs.statSync(inFile.path);
this.dataSize = stat.size;
console.info('dataSize: ' + this.dataSize);
// 关闭文件
fs.closeSync(inFile);
})
}
}
.height('100%')
.width('100%')
}
}
解压缩:
import { fileIo as fs} from '@kit.CoreFileKit';
import { BusinessError, zlib } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
build() {
Row() {
// 示例一:将测试文件data.txt压缩并归档到data.zip中。
Button('compressFile').onClick(() => {
let path = getContext(this).filesDir;
let inFile = path + '/data.txt';
let outFile = path + '/data.zip';
let options: zlib.Options = {};
zlib.compressFile(inFile, outFile, options).then((data: void) => {
console.info('compressFile success, data: ' + JSON.stringify(data));
}).catch((errData: BusinessError) => {
console.error(compressFile errCode: ${errData.code}, message: ${errData.message});
})
})
// 示例二:将data.zip文件解压到应用沙箱目录下。
Button('decompressFile').onClick(() => {
let path = getContext(this).filesDir;
let inFile = path + '/data.zip';
let outFile = path;
let options: zlib.Options = {};
zlib.decompressFile(inFile, outFile, options).then((data: void) => {
console.info('decompressFile success, data: ' + JSON.stringify(data));
}).catch((errData: BusinessError) => {
console.error(decompressFile errCode: ${errData.code}, message: ${errData.message});
})
})
}
.height('100%')
.width('100%')
}
}
import { fileIo as fs} from '@kit.CoreFileKit';
import { BusinessError, zlib } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State dataSize: number = 0; //用于保存原始数据的大小
build() {
Row() {
// 示例一:读取data.txt文件内容并存入一个缓冲区,调用compress接口压缩缓冲区中的数据到目标缓冲区,并将目标缓冲区的内容写入文件data.bin
Button('compress buffer').onClick(() => {
let path = getContext(this).filesDir;
let inFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let outFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 读取data.txt文件的内容,并存入缓冲区inBuf
let stat = fs.statSync(inFile.path);
let inBuf = new ArrayBuffer(stat.size);
let readLen = fs.readSync(inFile.fd, inBuf);
console.info(original size: ${stat.size}, read len: ${readLen});
// 获取原始数据的大小,并保存
this.dataSize = stat.size;
// 创建一个压缩对象实例
let zip = zlib.createZipSync();
// 获取一个目标缓冲区的上限
zip.compressBound(stat.size).then((data) => {
console.info(the max dest buf len is ${data});
// 目标缓冲区outBuf
let outBuf = new ArrayBuffer(data);
// 将inBuf中的数据压缩到outBuf中
zip.compress(outBuf, inBuf, readLen).then((zipOutInfo) => {
console.info(compress success, status ${zipOutInfo.status}, destLen ${zipOutInfo.destLen});
// 将outBuf中的数据写入到data.bin文件
let writeLen = fs.writeSync(outFile.fd, outBuf, { length: zipOutInfo.destLen });
console.info(write destBuf to data.bin, writeLen ${writeLen});
// 关闭文件
fs.closeSync(inFile.fd);
fs.closeSync(outFile.fd);
}).catch((errData: BusinessError) => {
console.error(errData is errCode:${errData.code} message:${errData.message});
})
}).catch((errData: BusinessError) => {
console.error(errData is errCode:${errData.code} message:${errData.message});
})
})
// 示例二:读取data.bin文件中的压缩数据并存入一个缓冲区,调用uncompress接口将缓冲区中的数据解压到目标缓冲区,并将目标缓冲区的内容写入文件data.txt
Button('uncompress buffer').onClick(() => {
let path = getContext(this).filesDir;
let inFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let outFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 读取data.bin文件中的压缩数据,并存入缓冲区inBuf
let stat = fs.statSync(inFile.path);
let inBuf = new ArrayBuffer(stat.size);
let readLen = fs.readSync(inFile.fd, inBuf);
console.info(compressed data size: ${stat.size}, read len: ${readLen});
// 创建一个目标缓冲区,此处的dataSize是我们进行数据压缩前保存的数据的原始大小
let outBuf = new ArrayBuffer(this.dataSize);
console.info(the dest buf size is ${this.dataSize});
// 创建一个压缩对象实例
let zip = zlib.createZipSync();
// 将inBuf中的数据解压缩outBuf中
zip.uncompress(outBuf, inBuf, readLen).then((zipOutInfo) => {
console.info(uncompress success, status ${zipOutInfo.status}, destLen ${zipOutInfo.destLen});
// 将outBuf中的数据写入到data.txt文件
let writeLen = fs.writeSync(outFile.fd, outBuf, { length: zipOutInfo.destLen });
console.info(write destBuf to data.txt, writeLen ${writeLen});
// 关闭文件
fs.closeSync(inFile.fd);
fs.closeSync(outFile.fd);
}).catch((errData: BusinessError) => {
console.error(errData is errCode:${errData.code} message:${errData.message});
})
})
}
.height('100%')
.width('100%')
}
}
import { fileIo as fs} from '@kit.CoreFileKit';
import { BusinessError, zlib } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
build() {
Row() {
// 示例一:从文件中不断读取数据进行压缩
Button('deflateFile').onClick(() => {
let path = getContext(this).filesDir;
let inFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let outFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
deflateFile(inFile, outFile).then(() => {
console.info('deflateFile success');
fs.closeSync(inFile.fd);
fs.closeSync(outFile.fd);
})
})
// 示例二:从文件中不断读取压缩数据进行解压
Button('inflateFile').onClick(() => {
let path = getContext(this).filesDir;
let inFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let outFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
inflateFile(inFile, outFile).then(() => {
console.info('deflateFile success');
fs.closeSync(inFile.fd);
fs.closeSync(outFile.fd);
})
})
}
.height('100%')
.width('100%')
}
}
// 从一个文件中,不断的读入数据,进行压缩,并写入到另一个文件中
async function deflateFile(src: fs.File, dest: fs.File) {
let flush = zlib.CompressFlushMode.NO_FLUSH;
let strm: zlib.ZStream = {}; //初始化一个压缩流
const BUFLEN = 4096;
let inBuf = new ArrayBuffer(BUFLEN); // 初始化一个输入缓冲区
let outBuf = new ArrayBuffer(BUFLEN); // 初始化一个输出缓冲区
// 创建一个压缩对象实例
let zip = zlib.createZipSync();
// 初始化流的状态
let initStatus = zip.deflateInit(strm, zlib.CompressLevel.COMPRESS_LEVEL_BEST_SPEED);
console.info('deflateInit ret: ' + (await initStatus).valueOf());
do {
// 从文件中读取数据到缓冲区
let readLen = fs.readSync(src.fd, inBuf);
console.info("readSync readLen: " + readLen);
flush = readLen == 0 ? zlib.CompressFlushMode.FINISH : zlib.CompressFlushMode.NO_FLUSH;
// 设置输入缓冲区
strm.availableIn = readLen;
strm.nextIn = inBuf;
do {
// 设置输出缓冲区
strm.availableOut = BUFLEN;
strm.nextOut = outBuf;
try {
// 压缩输入缓冲区中数据到输出缓冲区
let deflateStatus = zip.deflate(strm, flush);
console.info('deflate ret: ' + (await deflateStatus).valueOf());
// 更新流的状态
let innerStrm = zip.getZStream();
strm.availableIn = (await innerStrm).availableIn;
strm.nextIn = (await innerStrm).nextIn;
strm.availableOut = (await innerStrm).availableOut;
strm.nextOut = (await innerStrm).nextOut;
strm.totalIn = (await innerStrm).totalIn;
strm.totalOut = (await innerStrm).totalOut;
if (strm.availableOut != undefined) {
// 将已完成压缩的数据,写入到输出文件中
let have = BUFLEN - strm.availableOut;
let writeLen = fs.writeSync(dest.fd, outBuf, { length: have });
console.info(writeSync writeLen: ${writeLen});
}
} catch (err) {
console.error('deflate err: ' + JSON.stringify(err));
}
} while (strm.availableOut == 0); // 循环压缩输入缓冲区中剩余的数据,直到全部完成压缩
} while (flush != zlib.CompressFlushMode.FINISH); // 循环从文件中读取数据,直到数据全部读取
// 释放资源
zip.deflateEnd(strm);
}
// 从一个文件中,不断的读入已压缩的数据,进行解压,并写入到另一个文件中
async function inflateFile(src: fs.File, dest: fs.File) {
let status: zlib.ReturnStatus = zlib.ReturnStatus.OK;
let strm: zlib.ZStream = {}; //初始化一个压缩流
const BUFLEN = 4096;
let inBuf = new ArrayBuffer(BUFLEN); // 初始化一个输入缓冲区
let outBuf = new ArrayBuffer(BUFLEN); // 初始化一个输出缓冲区
// 创建一个压缩对象实例
let zip = zlib.createZipSync();
// 初始化流的状态
let initStatus = zip.inflateInit(strm);
console.info('inflateInit ret: ' + (await initStatus).valueOf());
do {
// 从文件中读取已压缩的数据到缓冲区
let readLen = fs.readSync(src.fd, inBuf);
console.info("readSync readLen: " + readLen);
if (readLen == 0) {
break;
}
// 设置输入缓冲区
strm.availableIn = readLen;
strm.nextIn = inBuf;
do {
// 设置输出缓冲区
strm.availableOut = BUFLEN;
strm.nextOut = outBuf;
try {
// 解压输入缓冲区中数据到输出缓冲区
let inflateStatus = zip.inflate(strm, zlib.CompressFlushMode.NO_FLUSH);
console.info('inflate ret: ' + (await inflateStatus).valueOf());
// 更新流的状态
let innerStrm = zip.getZStream();
strm.availableIn = (await innerStrm).availableIn;
strm.nextIn = (await innerStrm).nextIn;
strm.availableOut = (await innerStrm).availableOut;
strm.nextOut = (await innerStrm).nextOut;
strm.totalIn = (await innerStrm).totalIn;
strm.totalOut = (await innerStrm).totalOut;
if (strm.availableOut != undefined) {
// 将已完成解压的数据,写入到输出文件中
let have = BUFLEN - strm.availableOut;
let writeLen = fs.writeSync(dest.fd, outBuf, { length: have });
console.info(writeSync writeLen: ${writeLen});
}
} catch (err) {
console.error('inflate err: ' + JSON.stringify(err));
}
} while (strm.availableOut == 0) // 循环解压输入缓冲区中剩余的数据,直到全部完成解压
} while (status != zlib.ReturnStatus.STREAM_END.valueOf()) // 循环从文件中读取数据,直到数据全部读取
// 释放资源
zip.inflateEnd(strm);
}