Compress and decompress streamed or from-memory data, using input and output filters.
Create the sample source data.
Specify the page size, in bytes.
Create the destination buffer.
Create the output filter that will compress the sample source data.
Compress the sample source data and handle any errors.
Create the input filter that will decompress the compressed result from the previous step.
Decompress the compressed data.
Create a string from the decompressed data from the previous step.
Although the article uses a string to provide a simplified example, use this API when working with data that’s streamed to or from memory. For example, when reading from or writing to a file.
If you’re compressing and decompressing data that’s held entirely in memory, consider using
decompressed(using:). These functions provide a simple API to compress and decompress data in a single step.
Create the Source Data
Typically, your app dynamically generates the source data that it compresses, but for this example, the source data is a hard-coded string:
source contains the UTF-8 representation of the source string.
Specify the Page Size
Output instances compress and decompress pages of data. Specify the number of bytes in each page that are read from or written to a stream. Smaller values allow your app to report progress or perform other tasks at higher frequencies than larger values. However, larger values allow your app to compress or decompress using fewer steps, possibly in less time.
For this example, use a page size of 128 bytes:
Create the Compression Destination Buffer
Create a mutable, empty
Data structure to receive the compressed data:
Create the Output Filter
Output instance, and specify the operation as
Filter and the compression algorithm as
Algorithm. For more information about other compression algorithms, see
The final initializer parameter is a closure that the instance calls as it writes each compressed block of data to
Compress the Data
Iterate over the source data and call the
subdata(in:) method to copy
page chunks to
write(_:) method compresses each chunk and uses the closure specified in the
Output initializer to write the result to
compressed contains a compressed version of the original source data.
Handle any Errors That Occured During Compression.
The output filter’s initializer and write method can both throw errors. Your code should catch and handle any errors the output filter may have thrown during the compression stage.
Create the Decompression Destination Buffer
Create a mutable, empty
Data structure to receive the decompressed data:
Create the Input Filter
Create an InputFilter instance, and specify the operation as
Filter, and the compression algorithm as
The final initializer parameter is a closure the instance calls as it reads each compressed block of data.
Decompress the Data
You iterate over the compressed data by repeatedly calling
read, until the function returns nil. With each iteration, append the data returned by the input filter to
Handle any Errors That Occurred During Decompression.
The input filter’s initializer and read method can both throw errors. Your code should catch and handle any errors the output filter may have thrown during the decompression stage.
Create a String from the Decompressed Data
init(data: to recreate a string from the decompressed data:
decompressed contains the original text shown in Create the Source Data.
Select Input and Output Filters Based on Requirements
You’re not tied to using output filters for compression and input filters for decompression. You should select the appropriate compressor-decompressor based on your app’s requirements.
For example, the following code shows an
Input instance as the compressor:
The following shows an
Output instance as the decompressor: