Skip to main content

Quick start guide

This guide will walk you through creating your first compression and decompression program using the Zstandard C library.

Prerequisites

Before starting, make sure you have:
  • Zstandard library installed (see Installation)
  • A C compiler (gcc, clang, or equivalent)
  • Basic familiarity with C programming

Simple compression example

Let’s create a simple program that compresses a file. This example is based on the official simple_compression.c from the Zstandard repository.
1

Create the compression program

Create a file named compress.c with the following code:
compress.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zstd.h>

static void compress_file(const char* input_file, const char* output_file)
{
    // Read input file
    FILE* fin = fopen(input_file, "rb");
    if (!fin) {
        fprintf(stderr, "Failed to open input file\n");
        exit(1);
    }
    
    fseek(fin, 0, SEEK_END);
    size_t fSize = ftell(fin);
    fseek(fin, 0, SEEK_SET);
    
    void* fBuff = malloc(fSize);
    if (!fBuff) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
    }
    
    fread(fBuff, 1, fSize, fin);
    fclose(fin);
    
    // Compress the data
    size_t const cBuffSize = ZSTD_compressBound(fSize);
    void* const cBuff = malloc(cBuffSize);
    if (!cBuff) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
    }
    
    size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1);
    if (ZSTD_isError(cSize)) {
        fprintf(stderr, "Compression error: %s\n", ZSTD_getErrorName(cSize));
        exit(1);
    }
    
    // Write compressed data to output file
    FILE* fout = fopen(output_file, "wb");
    if (!fout) {
        fprintf(stderr, "Failed to open output file\n");
        exit(1);
    }
    
    fwrite(cBuff, 1, cSize, fout);
    fclose(fout);
    
    printf("%s : %zu -> %zu bytes (%.2f%% compression)\n",
           input_file, fSize, cSize, 
           (1.0 - (double)cSize / fSize) * 100);
    
    free(fBuff);
    free(cBuff);
}

int main(int argc, char** argv)
{
    if (argc != 3) {
        printf("Usage: %s INPUT_FILE OUTPUT_FILE\n", argv[0]);
        return 1;
    }
    
    compress_file(argv[1], argv[2]);
    return 0;
}
2

Create the decompression program

Create a file named decompress.c:
decompress.c
#include <stdio.h>
#include <stdlib.h>
#include <zstd.h>

static void decompress_file(const char* input_file, const char* output_file)
{
    // Read compressed file
    FILE* fin = fopen(input_file, "rb");
    if (!fin) {
        fprintf(stderr, "Failed to open input file\n");
        exit(1);
    }
    
    fseek(fin, 0, SEEK_END);
    size_t cSize = ftell(fin);
    fseek(fin, 0, SEEK_SET);
    
    void* cBuff = malloc(cSize);
    if (!cBuff) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
    }
    
    fread(cBuff, 1, cSize, fin);
    fclose(fin);
    
    // Get the decompressed size from the frame header
    unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
    if (rSize == ZSTD_CONTENTSIZE_ERROR) {
        fprintf(stderr, "%s: not compressed by zstd!\n", input_file);
        exit(1);
    }
    if (rSize == ZSTD_CONTENTSIZE_UNKNOWN) {
        fprintf(stderr, "%s: original size unknown!\n", input_file);
        exit(1);
    }
    
    void* const rBuff = malloc((size_t)rSize);
    if (!rBuff) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
    }
    
    // Decompress
    size_t const dSize = ZSTD_decompress(rBuff, rSize, cBuff, cSize);
    if (ZSTD_isError(dSize)) {
        fprintf(stderr, "Decompression error: %s\n", ZSTD_getErrorName(dSize));
        exit(1);
    }
    
    // Write decompressed data to output file
    FILE* fout = fopen(output_file, "wb");
    if (!fout) {
        fprintf(stderr, "Failed to open output file\n");
        exit(1);
    }
    
    fwrite(rBuff, 1, dSize, fout);
    fclose(fout);
    
    printf("%s : %zu -> %zu bytes\n", input_file, cSize, (size_t)rSize);
    printf("%s correctly decompressed to %s\n", input_file, output_file);
    
    free(cBuff);
    free(rBuff);
}

int main(int argc, char** argv)
{
    if (argc != 3) {
        printf("Usage: %s COMPRESSED_FILE OUTPUT_FILE\n", argv[0]);
        return 1;
    }
    
    decompress_file(argv[1], argv[2]);
    return 0;
}
3

Compile the programs

Compile both programs with the Zstandard library:
# Compile compression program
gcc -o compress compress.c -lzstd

# Compile decompression program
gcc -o decompress decompress.c -lzstd
If you installed Zstandard in a custom location, you may need to specify the include and library paths:
gcc -o compress compress.c -I/path/to/include -L/path/to/lib -lzstd
4

Test the programs

Create a test file and compress it:
# Create a test file
echo "Hello, Zstandard! This is a test file." > test.txt

# Compress the file
./compress test.txt test.txt.zst

# Decompress the file
./decompress test.txt.zst test_restored.txt

# Verify the output
cat test_restored.txt

Expected output

When you run the compression program, you should see output like:
test.txt : 40 -> 28 bytes (30.00% compression)
When you run the decompression program:
test.txt.zst : 28 -> 40 bytes
test.txt.zst correctly decompressed to test_restored.txt

Understanding the API

The examples above use the Simple Core API, which is perfect for single-step compression:

Key functions

ZSTD_compressBound()

Calculates the maximum compressed size for a given input size. This guarantees that the destination buffer is large enough:
size_t const cBuffSize = ZSTD_compressBound(fSize);

ZSTD_compress()

Compresses source content as a single zstd compressed frame:
size_t ZSTD_compress(void* dst, size_t dstCapacity,
                     const void* src, size_t srcSize,
                     int compressionLevel);
  • dst: Destination buffer for compressed data
  • dstCapacity: Size of destination buffer
  • src: Source data to compress
  • srcSize: Size of source data
  • compressionLevel: Compression level (1-22, or negative for fast mode)

ZSTD_getFrameContentSize()

Returns the decompressed content size stored in the frame header:
unsigned long long const rSize = ZSTD_getFrameContentSize(cBuff, cSize);
Always check for ZSTD_CONTENTSIZE_ERROR and ZSTD_CONTENTSIZE_UNKNOWN when calling this function.

ZSTD_decompress()

Decompresses a zstd compressed frame:
size_t ZSTD_decompress(void* dst, size_t dstCapacity,
                       const void* src, size_t compressedSize);

Error handling

Always check if operations failed using ZSTD_isError() and get error messages with ZSTD_getErrorName():
if (ZSTD_isError(cSize)) {
    fprintf(stderr, "Error: %s\n", ZSTD_getErrorName(cSize));
}

Compression levels

Experiment with different compression levels to find the right balance for your use case:
// Faster compression, lower ratio
ZSTD_compress(dst, dstSize, src, srcSize, -5);
Decompression speed remains roughly the same regardless of the compression level used.

Performance tips

  1. Reuse contexts for multiple compressions to avoid malloc/free overhead (see ZSTD_compressCCtx())
  2. Use streaming APIs for large files that don’t fit in memory (see ZSTD_compressStream())
  3. Train dictionaries for small data compression to dramatically improve ratios
  4. Choose appropriate compression levels based on your speed/ratio requirements

Next steps

Now that you have a working example, explore more advanced features:

Streaming compression

Learn how to compress data that doesn’t fit in memory using streaming APIs

Dictionary compression

Improve compression ratios for small data by training custom dictionaries

Context reuse

Optimize performance when compressing multiple files by reusing contexts

API reference

Explore the complete Zstandard API documentation

Complete example source

The complete, production-ready examples used as the basis for this guide can be found in the official Zstandard repository:

Build docs developers (and LLMs) love