• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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