1# Compressing and Decompressing Files 2 3This topic describes how to use functions in common compression and decompression scenarios. 4 5## Available APIs 6 7For details about more APIs and their usage, see [Zip](../../reference/apis-basic-services-kit/js-apis-zlib.md). 8 9| API | Description | 10| ------------------------------------------------------------ | ---------------------------- | 11| compressFile(inFile: string, outFile: string, options: Options): Promise<void> | Compresses a file. | 12| decompressFile(inFile: string, outFile: string, options?: Options): Promise<void> | Decompresses a file. | 13| compress(dest: ArrayBuffer, source: ArrayBuffer, sourceLen?: number): Promise<ZipOutputInfo> | Compresses the source buffer into the destination buffer. | 14| compressBound(sourceLen: number): Promise<number> | Calculates the upper limit of the compression size to return. | 15| uncompress(dest:ArrayBuffer, source: ArrayBuffer, sourceLen?: number): Promise<ZipOutputInfo> | Decompresses the compressed data into an original uncompressed one. | 16| deflate(strm: ZStream, flush: CompressFlushMode): Promise<ReturnStatus> | Deflates data. | 17| inflate(strm: ZStream, flush: CompressFlushMode): Promise<ReturnStatus> | Inflates data.| 18 19## How to Develop 20 21### Environment Preparations 22 23Create a test file **data.txt** in the application sandbox directory and write data for testing. The sample code is as follows: 24 25 ```ts 26 import { fileIo as fs} from '@kit.CoreFileKit' 27 import { BusinessError, zlib } from '@kit.BasicServicesKit' 28 29 @Entry 30 @Component 31 struct Index { 32 @State dataSize: number = 0; 33 34 build() { 35 Row() { 36 Column() { 37 // Create the data.txt file and write test data. 38 Button('Create a test file data.txt').onClick(() => { 39 let path = getContext(this).filesDir; 40 // Create the data.txt file. 41 let inFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 42 // Write test data. 43 for (let index = 0; index < 100; index++) { 44 fs.writeSync(inFile.fd, index + ': hello world, hello world, hello world, hello world, hello world.\n'); 45 } 46 // Obtain the original size of the test data and save it to dataSize. 47 let stat = fs.statSync(inFile.path); 48 this.dataSize = stat.size; 49 console.info('dataSize: ' + this.dataSize); 50 // Close the file. 51 fs.closeSync(inFile); 52 }) 53 } 54 } 55 .height('100%') 56 .width('100%') 57 } 58 } 59 ``` 60 61### Compressing and Decompressing .zip Files 62 63Use [zlib.compressFile()](../../reference/apis-basic-services-kit/js-apis-zlib.md#zlibcompressfile9-1) to compress the **data.txt** into to the **data.zip** file, and use [zlib.decompressFile()](../../reference/apis-basic-services-kit/js-apis-zlib.md#zlibdecompressfile9-1) to decompress the .zip file to the application sandbox directory. The sample code is as follows: 64 65 ```ts 66 import { fileIo as fs} from '@kit.CoreFileKit' 67 import { BusinessError, zlib } from '@kit.BasicServicesKit' 68 69 @Entry 70 @Component 71 struct Index { 72 build() { 73 Row() { 74 // Example 1: Compress the data.txt file into the data.zip file. 75 Button('compressFile').onClick(() => { 76 let path = getContext(this).filesDir; 77 let inFile = path + '/data.txt'; 78 let outFile = path + '/data.zip'; 79 let options: zlib.Options = {}; 80 zlib.compressFile(inFile, outFile, options).then((data: void) => { 81 console.info('compressFile success, data: ' + JSON.stringify(data)); 82 }).catch((errData: BusinessError) => { 83 console.error(`compressFile errCode: ${errData.code}, message: ${errData.message}`); 84 }) 85 }) 86 87 // Example 2: Decompress the data.zip file to the application sandbox directory. 88 Button('decompressFile').onClick(() => { 89 let path = getContext(this).filesDir; 90 let inFile = path + '/data.zip'; 91 let outFile = path; 92 let options: zlib.Options = {}; 93 zlib.decompressFile(inFile, outFile, options).then((data: void) => { 94 console.info('decompressFile success, data: ' + JSON.stringify(data)); 95 }).catch((errData: BusinessError) => { 96 console.error(`decompressFile errCode: ${errData.code}, message: ${errData.message}`); 97 }) 98 }) 99 } 100 .height('100%') 101 .width('100%') 102 } 103 } 104 ``` 105 106### Compressing and Decompressing Buffers of Known Sizes 107 108For data in a buffer with a known size, use [compress()](../../reference/apis-basic-services-kit/js-apis-zlib.md#compress12) to compress the data into a destination buffer, [compressBound()](../../reference/apis-basic-services-kit/js-apis-zlib.md#compressbound12) to calculate the upper limit of the compression size of the destination buffer, and [uncompress()](../../reference/apis-basic-services-kit/js-apis-zlib.md#uncompress12) to decompress the buffer that stores the compressed data. To check the size of the destination buffer after decompression, obtain and save the original data size before compression. The sample code is as follows: 109 110 ```ts 111 import { fileIo as fs} from '@kit.CoreFileKit' 112 import { BusinessError, zlib } from '@kit.BasicServicesKit' 113 114 @Entry 115 @Component 116 struct Index { 117 @State dataSize: number = 0; // Size of the original data. 118 119 build() { 120 Row() { 121 // Example 1: Read the data.txt file and save it to a buffer. Call the compress API to compress the data in the source buffer to the destination buffer and write the content in the destination buffer to the data.bin file. 122 Button('compress buffer').onClick(() => { 123 let path = getContext(this).filesDir; 124 let inFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 125 let outFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 126 // Read the content of the data.txt file and save the content to the buffer inBuf. 127 let stat = fs.statSync(inFile.path); 128 let inBuf = new ArrayBuffer(stat.size); 129 let readLen = fs.readSync(inFile.fd, inBuf); 130 console.info(`original size: ${stat.size}, read len: ${readLen}`); 131 // Obtain the size of the original data and save it. 132 this.dataSize = stat.size; 133 // Create a compressed object instance. 134 let zip = zlib.createZipSync(); 135 // Obtain the upper limit of a destination buffer. 136 zip.compressBound(stat.size).then((data) => { 137 console.info(`the max dest buf len is ${data}`); 138 // Destination buffer outBuf. 139 let outBuf = new ArrayBuffer(data); 140 // Compress the data in inBuf to outBuf. 141 zip.compress(outBuf, inBuf, readLen).then((zipOutInfo) => { 142 console.info(`compress success, status ${zipOutInfo.status}, destLen ${zipOutInfo.destLen}`); 143 // Write the data in outBuf to the data.bin file. 144 let writeLen = fs.writeSync(outFile.fd, outBuf, { length: zipOutInfo.destLen }); 145 console.info(`write destBuf to data.bin, writeLen ${writeLen}`); 146 // Close the file. 147 fs.closeSync(inFile.fd); 148 fs.closeSync(outFile.fd); 149 }).catch((errData: BusinessError) => { 150 console.error(`errData is errCode:${errData.code} message:${errData.message}`); 151 }) 152 }).catch((errData: BusinessError) => { 153 console.error(`errData is errCode:${errData.code} message:${errData.message}`); 154 }) 155 }) 156 157 // Example 2: Read the compressed data in the data.bin file and save it to a buffer. Call the uncompress API to decompress the data in the source buffer to the destination buffer and write the content in the destination buffer to the data.txt file. 158 Button('uncompress buffer').onClick(() => { 159 let path = getContext(this).filesDir; 160 let inFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 161 let outFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 162 // Read the compressed data in the data.bin file and save the data to the buffer inBuf. 163 let stat = fs.statSync(inFile.path); 164 let inBuf = new ArrayBuffer(stat.size); 165 let readLen = fs.readSync(inFile.fd, inBuf); 166 console.info(`compressed data size: ${stat.size}, read len: ${readLen}`); 167 // Create a destination buffer. dataSize indicates the original size of the data saved before compression. 168 let outBuf = new ArrayBuffer(this.dataSize); 169 console.info(`the dest buf size is ${this.dataSize}`); 170 // Create a compressed object instance. 171 let zip = zlib.createZipSync(); 172 // Decompress the data in inBuf to outBuf. 173 zip.uncompress(outBuf, inBuf, readLen).then((zipOutInfo) => { 174 console.info(`uncompress success, status ${zipOutInfo.status}, destLen ${zipOutInfo.destLen}`); 175 // Write the data in outBuf to the data.txt file. 176 let writeLen = fs.writeSync(outFile.fd, outBuf, { length: zipOutInfo.destLen }); 177 console.info(`write destBuf to data.txt, writeLen ${writeLen}`); 178 // Close the file. 179 fs.closeSync(inFile.fd); 180 fs.closeSync(outFile.fd); 181 }).catch((errData: BusinessError) => { 182 console.error(`errData is errCode:${errData.code} message:${errData.message}`); 183 }) 184 }) 185 } 186 .height('100%') 187 .width('100%') 188 } 189 } 190 ``` 191 192### Compressing and Decompressing Buffers of Unknown Sizes 193 194For data in a buffer with an unknown size, use [deflate()](../../reference/apis-basic-services-kit/js-apis-zlib.md#deflate12) to compress the data read from an original input stream and [inflate()](../../reference/apis-basic-services-kit/js-apis-zlib.md#inflate12) to decompress the data read from a compressed input stream. The sample code is as follows: 195 196 ```ts 197 import { fileIo as fs} from '@kit.CoreFileKit' 198 import { BusinessError, zlib } from '@kit.BasicServicesKit' 199 200 @Entry 201 @Component 202 struct Index { 203 build() { 204 Row() { 205 // Example 1: Continuously read data from a file for compression. 206 Button('deflateFile').onClick(() => { 207 let path = getContext(this).filesDir; 208 let inFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 209 let outFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 210 deflateFile(inFile, outFile).then(() => { 211 console.info('deflateFile success'); 212 fs.closeSync(inFile.fd); 213 fs.closeSync(outFile.fd); 214 }) 215 }) 216 217 // Example 2: Continuously read compressed data from the file for decompression. 218 Button('inflateFile').onClick(() => { 219 let path = getContext(this).filesDir; 220 let inFile = fs.openSync(path + '/data.bin', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 221 let outFile = fs.openSync(path + '/data.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 222 inflateFile(inFile, outFile).then(() => { 223 console.info('deflateFile success'); 224 fs.closeSync(inFile.fd); 225 fs.closeSync(outFile.fd); 226 }) 227 }) 228 } 229 .height('100%') 230 .width('100%') 231 } 232 } 233 234 // Continuously read data from a file, compress the data, and write the data to another file. 235 async function deflateFile(src: fs.File, dest: fs.File) { 236 let flush = zlib.CompressFlushMode.NO_FLUSH; 237 let strm: zlib.ZStream = {}; // Initialize a compression stream. 238 const BUFLEN = 4096; 239 let inBuf = new ArrayBuffer(BUFLEN); // Initialize an input buffer. 240 let outBuf = new ArrayBuffer(BUFLEN); // Initialize an output buffer. 241 // Create a compressed object instance. 242 let zip = zlib.createZipSync(); 243 // Initialize the stream status. 244 let initStatus = zip.deflateInit(strm, zlib.CompressLevel.COMPRESS_LEVEL_BEST_SPEED); 245 console.info('deflateInit ret: ' + (await initStatus).valueOf()); 246 do { 247 // Read data from a file to a buffer. 248 let readLen = fs.readSync(src.fd, inBuf); 249 console.info("readSync readLen: " + readLen); 250 flush = readLen == 0 ? zlib.CompressFlushMode.FINISH : zlib.CompressFlushMode.NO_FLUSH; 251 // Set the input buffer. 252 strm.availableIn = readLen; 253 strm.nextIn = inBuf; 254 do { 255 // Set the output buffer. 256 strm.availableOut = BUFLEN; 257 strm.nextOut = outBuf; 258 try { 259 // Compress the data in the input buffer to the output buffer. 260 let deflateStatus = zip.deflate(strm, flush); 261 console.info('deflate ret: ' + (await deflateStatus).valueOf()); 262 // Update the stream status. 263 let innerStrm = zip.getZStream(); 264 strm.availableIn = (await innerStrm).availableIn; 265 strm.nextIn = (await innerStrm).nextIn; 266 strm.availableOut = (await innerStrm).availableOut; 267 strm.nextOut = (await innerStrm).nextOut; 268 strm.totalIn = (await innerStrm).totalIn; 269 strm.totalOut = (await innerStrm).totalOut; 270 271 if (strm.availableOut != undefined) { 272 // Write the compressed data to the output file. 273 let have = BUFLEN - strm.availableOut; 274 let writeLen = fs.writeSync(dest.fd, outBuf, { length: have }); 275 console.info(`writeSync writeLen: ${writeLen}`); 276 } 277 } catch (err) { 278 console.error('deflate err: ' + JSON.stringify(err)); 279 } 280 } while (strm.availableOut == 0); // Compress the remaining data in the input buffer cyclically until all data is compressed. 281 } while (flush != zlib.CompressFlushMode.FINISH); // Read data from the file cyclically until all data is read. 282 // Release resources. 283 zip.deflateEnd(strm); 284 } 285 286 // Continuously read compressed data from a file, decompress the data, and write the data to another file. 287 async function inflateFile(src: fs.File, dest: fs.File) { 288 let status: zlib.ReturnStatus = zlib.ReturnStatus.OK; 289 let strm: zlib.ZStream = {}; // Initialize a compression stream. 290 const BUFLEN = 4096; 291 let inBuf = new ArrayBuffer(BUFLEN); // Initialize an input buffer. 292 let outBuf = new ArrayBuffer(BUFLEN); // Initialize an output buffer. 293 // Create a compressed object instance. 294 let zip = zlib.createZipSync(); 295 // Initialize the stream status. 296 let initStatus = zip.inflateInit(strm); 297 console.info('inflateInit ret: ' + (await initStatus).valueOf()); 298 do { 299 // Read the compressed data from the file to the buffer. 300 let readLen = fs.readSync(src.fd, inBuf); 301 console.info("readSync readLen: " + readLen); 302 if (readLen == 0) { 303 break; 304 } 305 // Set the input buffer. 306 strm.availableIn = readLen; 307 strm.nextIn = inBuf; 308 do { 309 // Set the output buffer. 310 strm.availableOut = BUFLEN; 311 strm.nextOut = outBuf; 312 try { 313 // Decompress the data in the input buffer to the output buffer. 314 let inflateStatus = zip.inflate(strm, zlib.CompressFlushMode.NO_FLUSH); 315 console.info('inflate ret: ' + (await inflateStatus).valueOf()); 316 // Update the stream status. 317 let innerStrm = zip.getZStream(); 318 strm.availableIn = (await innerStrm).availableIn; 319 strm.nextIn = (await innerStrm).nextIn; 320 strm.availableOut = (await innerStrm).availableOut; 321 strm.nextOut = (await innerStrm).nextOut; 322 strm.totalIn = (await innerStrm).totalIn; 323 strm.totalOut = (await innerStrm).totalOut; 324 325 if (strm.availableOut != undefined) { 326 // Write the decompressed data to the output file. 327 let have = BUFLEN - strm.availableOut; 328 let writeLen = fs.writeSync(dest.fd, outBuf, { length: have }); 329 console.info(`writeSync writeLen: ${writeLen}`); 330 } 331 } catch (err) { 332 console.error('inflate err: ' + JSON.stringify(err)); 333 } 334 } while (strm.availableOut == 0) // Decompress the remaining data in the input buffer cyclically until all data is decompressed. 335 } while (status != zlib.ReturnStatus.STREAM_END.valueOf()) // Read data from the file cyclically until all data is read. 336 // Release resources. 337 zip.inflateEnd(strm); 338 } 339 ``` 340 341## FAQs 342 3431. 17800005 Incorrect Input Data 344 345 For details about the possible causes and solution, see [error code 17800005](../../reference/apis-basic-services-kit/errorcode-zlib.md#17800005-incorrect-input-data). 346 3472. 17800007 Incorrect Input Buffer 348 349 For details about the possible causes and solution, see [error code 17800007](../../reference/apis-basic-services-kit/errorcode-zlib.md#17800007-incorrect-input-buffer). 350