实现文件解压缩和数据流解压缩

实现文件解压缩和数据流解压缩


HarmonyOS
2024-05-22 22:34:14
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
bhtlilly

目前系统提供了两种方式去做解压缩:一种是用zlib接口实现文件解压缩,另一种是用ndk实现arraybuffer解压缩。另外三方库提供了js库pako,pako提供gzip和deflate等格式压缩解压码功能。

用zlib接口实现文件解压缩

以下是实现zlib接口的demo,预先在resource/rawfile下放入icon.png和ikun.zip(目前只支持zip)。

import zlib from '@ohos.zlib'; 
import { BusinessError } from '@ohos.base'; 
import common from '@ohos.app.ability.common'; 
import fs from '@ohos.file.fs'; 
import fileIo from '@ohos.file.fs'; 
 
@Entry 
@Component 
struct Index { 
  @State message1: string = '压缩'; 
  @State message2: string = '解压'; 
  private context = getContext(this) as common.UIAbilityContext; 
  // 指定压缩的文件夹路径或者文件路径,路径必须为沙箱路径,沙箱路径可以通过context获取,可参考 
  //stage: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-inner-application-context.md 
  @State inFile: string = 'icon.png'; 
 
  // 指定的压缩结果的文件路径。 
  @State outFile: string = 'icon.zip'; 
 
  // 压缩的配置参数。 
  // https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-zlib.md#options 
  @State options: zlib.Options = { 
    level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION, 
    memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT, 
    strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY 
  }; 
 
  @State deInFile: string = 'ikun.zip'; 
  @State deOptions: zlib.Options = { 
    level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION 
  }; 
 
 
  compressFile() { 
    this.context.resourceManager.getRawFileContent(this.inFile, (err: BusinessError, data: Uint8Array) => { 
      if (err != null) { 
        console.error(`compressFile open xxx.zip failed: ${err.message}`) 
      } else { 
        let sandboxPath = this.context.filesDir; 
        let filePath = sandboxPath + "/" + this.inFile; 
        console.log(filePath) 
        let file: fileIo.File = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); 
        fs.writeSync(file.fd, data.buffer); 
        // 拷贝文件到沙箱,为了简便,这里是直接getrawfilecontent然后写入,当文件过大时内存压力会很大,如需优化,可通过buffer进行读取 
        fs.close(file.fd); 
        zlib.compressFile(filePath, sandboxPath + "/" + this.outFile, this.options).then((data: void) => { 
          console.info('compressFile success. data: ' + JSON.stringify(data)); 
        }).catch((errData: BusinessError) => { 
          console.error(`compressFile errData is errCode:${errData.code}  message:${errData.message}`); 
        }) 
      } 
    }) 
  } 
 
  decompressFile(){ 
    this.context.resourceManager.getRawFileContent(this.deInFile, (err: BusinessError, data: Uint8Array) => { 
      if (err != null) { 
        console.error(`open xxx.zip failed: ${err.message}`); 
      } else { 
        let sandboxPath = this.context.filesDir; 
        let filePath = sandboxPath + "/" + this.deInFile; 
        console.log(filePath) 
        let file: fileIo.File = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); 
        fs.writeSync(file.fd, data.buffer); 
        // 拷贝文件到沙箱,为了简便,这里是直接getrawfilecontent然后写入,当文件过大时内存压力会很大,如需优化,可通过buffer进行读取 
        fs.close(file.fd); 
        zlib.decompressFile(filePath, sandboxPath, this.options).then((data: void) => { 
          console.info('compressFile success. data: ' + JSON.stringify(data)); 
        }).catch((errData: BusinessError) => { 
          console.error(`compressFile errData is errCode:${errData.code}  message:${errData.message}`); 
        }) 
      } 
    }) 
  } 
 
  build() { 
    Row() { 
      Column() { 
        Button(this.message1) 
          .fontSize(20) 
          .fontWeight(FontWeight.Bold) 
          .onClick(()=>{ 
            this.compressFile(); 
          }) 
          .margin({bottom: 30}) 
        Button(this.message2) 
          .fontSize(20) 
          .fontWeight(FontWeight.Bold) 
          .onClick(()=>{ 
            this.decompressFile(); 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

用napi的方式去解压缩

使用NDK记得:CMakeLists.txt的target_link_libraries 添加依赖的so,其中zlib的为libz.so 
压缩: 
int compressToGzip(const char *input, int inputSize, char *output, 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; 
zs.avail_out = (uInt)outputSize; 
 zs.next_out = (Bytef *)output; 
// "Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib 
deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); 
deflate(&zs, Z_FINISH); 
deflateEnd(&zs); 
return zs.total_out; 
 } 
  
解压 
int decompresGzip(const char *input, int inputSize, char *output, 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; 
zs.avail_out = (uInt)outputSize; 
 zs.next_out = (Bytef *)output; 
// "Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib 
inflateInit2(&zs, 15 | 16); 
inflate(&zs, Z_FINISH); 
inflateEnd(&zs); 
return zs.total_out; 
 }

用pako方式解压缩arraybuffer

首先用命令行安装pako三方库

 ohpm install pako 
  ohpm install @types/pako --save-dev //import pako 的时候语法报错。其原因是pako包内不含类型声明,需要 @types/pako 下载这个包的声明文件,从而解决语法的报错。

pako使用

import pako from 'pako' 
  
// Deflate 
// 
const input = new Uint8Array(); 
//... fill input data here 
const output = pako.deflate(input); 
  
// Inflate (simple wrapper can throw exception on broken stream) 
// 
const compressed = new Uint8Array(); 
//... fill data to uncompress here 
try { 
  const result = pako.inflate(compressed); 
  // ... continue processing 
} catch (err) { 
  console.log(err); 
} 
  
const deflator = new pako.Deflate(); 
  
deflator.push(chunk1, false); 
deflator.push(chunk2); // second param is false by default. 
... 
deflator.push(chunk_last, true); // `true` says this chunk is last 
  
if (deflator.err) { 
  console.log(deflator.msg); 
} 
  
const output = deflator.result; 
  
  
const inflator = new pako.Inflate(); 
  
inflator.push(chunk1); 
inflator.push(chunk2); 
... 
inflator.push(chunk_last); // no second param because end is auto-detected 
  
if (inflator.err) { 
  console.log(inflator.msg); 
} 
  
const output = inflator.result;**
分享
微博
QQ
微信
回复
2024-05-23 16:26:09
相关问题
如何解压有密码的压缩
608浏览 • 0回复 待解决
使用http模块实现数据流请求
372浏览 • 1回复 待解决
鸿蒙视频压缩怎么实现
7024浏览 • 1回复 待解决
网络请求使用gzip压缩数据
596浏览 • 1回复 待解决
supermap iManager 解压即用包
1162浏览 • 1回复 待解决
如何实现对字节数组进行解压
499浏览 • 0回复 待解决
zlib.decompressFile()解压报错如何分析
487浏览 • 1回复 待解决
是否有将文件压缩打包成zip的API?
338浏览 • 1回复 待解决
如何将PixelMap压缩到指定大小
495浏览 • 1回复 待解决
如何将图片PixelMap压缩到指定大小
509浏览 • 1回复 待解决
图片压缩指定宽高和限制大小
360浏览 • 1回复 待解决