xz

package module
v0.1.41 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: BSD-3-Clause Imports: 12 Imported by: 0

README

Package xz

This Go language package supports the reading and writing of xz compressed streams. It includes also a gxz command for compressing and decompressing data. The package is completely written in Go and doesn't have any dependency on any C code.

The package is currently under development and APIs are subject to change. Single-threaded decompression performance has been optimized using register caching and manual inlining. Additionally, the package supports multi-threaded parallel block decompression and provides APIs for block-level random access.

Using the API

The following example program shows how to use the API.

package main

import (
    "bytes"
    "io"
    "log"
    "os"

    "github.com/unxed/xz"
)

func main() {
    const text = "The quick brown fox jumps over the lazy dog.\n"
    var buf bytes.Buffer
    // compress text
    w, err := xz.NewWriter(&buf)
    if err != nil {
        log.Fatalf("xz.NewWriter error %s", err)
    }
    if _, err := io.WriteString(w, text); err != nil {
        log.Fatalf("WriteString error %s", err)
    }
    if err := w.Close(); err != nil {
        log.Fatalf("w.Close error %s", err)
    }
    // decompress buffer and write output to stdout
    r, err := xz.NewReader(&buf)
    if err != nil {
        log.Fatalf("NewReader error %s", err)
    }
    if _, err = io.Copy(os.Stdout, r); err != nil {
        log.Fatalf("io.Copy error %s", err)
    }
}

Parallel Decompression

For streams containing multiple independent blocks, the package supports concurrent block decompression using a worker pool. This utilizes multiple CPU cores to improve decoding throughput.

To use the parallel reader, the input stream must implement io.ReaderAt to facilitate concurrent offset-based reads.

package main

import (
    "bytes"
    "io"
    "log"
    "os"

    "github.com/unxed/xz"
)

func main() {
    // Read compressed data (must support io.ReaderAt)
    data, err := os.ReadFile("example.xz")
    if err != nil {
        log.Fatal(err)
    }
    rAt := bytes.NewReader(data)

    // Create parallel reader
    cfg := xz.ReaderConfig{}
    pr, err := cfg.NewParallelReader(rAt, int64(len(data)))
    if err != nil {
        log.Fatalf("NewParallelReader error: %s", err)
    }
    defer pr.Close()

    // Read decompressed output
    if _, err = io.Copy(os.Stdout, pr); err != nil {
        log.Fatalf("io.Copy error: %s", err)
    }
}

Block-Level Random Access

The XZ backward-linked indexes can be parsed to extract block boundaries, enabling direct decompression of individual blocks without sequential reading of the entire file.

// Parse block boundaries from seekable reader
blocks, err := xz.ParseBlocks(readerAt, size)
if err != nil {
    log.Fatal(err)
}

// Decompress individual blocks independently
for _, block := range blocks {
    // Seek to block start
    _, err := readerAt.Seek(block.Offset, io.SeekStart)
    if err != nil {
        log.Fatal(err)
    }

    // Initialize standalone block reader
    br, err := xz.ReaderConfig{}.NewBlockReader(readerAt, block.StreamFlags)
    if err != nil {
        log.Fatal(err)
    }

    // Decompress only this block
    if _, err = io.Copy(os.Stdout, br); err != nil {
        log.Fatal(err)
    }
}

Documentation

You can find the full documentation at pkg.go.dev.

Using the gxz compression tool

The package includes a gxz command line utility for compression and decompression.

Use following command for installation:

$ go get github.com/unxed/xz/cmd/gxz

To test it call the following command.

$ gxz bigfile

After some time a much smaller file bigfile.xz will replace bigfile. To decompress it use the following command.

$ gxz -d bigfile.xz

Security & Vulnerabilities

The security policy is documented in SECURITY.md.

The software is not affected by the supply chain attack on the original xz implementation, CVE-2024-3094. This implementation doesn't share any files with the original xz implementation and no patches or pull requests are accepted without a review.

All security advisories for this project are published under github.com/unxed/xz/security/advisories.

Documentation

Overview

Package xz supports the compression and decompression of xz files. It supports version 1.0.4 of the specification without the non-LZMA2 filters. See http://tukaani.org/xz/xz-file-format-1.0.4.txt

Example
const text = "The quick brown fox jumps over the lazy dog."
var buf bytes.Buffer

// compress text
w, err := NewWriter(&buf)
if err != nil {
	log.Fatalf("NewWriter error %s", err)
}
if _, err := io.WriteString(w, text); err != nil {
	log.Fatalf("WriteString error %s", err)
}
if err := w.Close(); err != nil {
	log.Fatalf("w.Close error %s", err)
}

// decompress buffer and write result to stdout
r, err := NewReader(&buf)
if err != nil {
	log.Fatalf("NewReader error %s", err)
}
if _, err = io.Copy(os.Stdout, r); err != nil {
	log.Fatalf("io.Copy error %s", err)
}
Output:
The quick brown fox jumps over the lazy dog.

Index

Examples

Constants

View Source
const (
	None   byte = 0x0
	CRC32  byte = 0x1
	CRC64  byte = 0x4
	SHA256 byte = 0xa
)

Constants for the checksum methods supported by xz.

View Source
const HeaderLen = 12

HeaderLen provides the length of the xz file header.

Variables

This section is empty.

Functions

func ValidHeader

func ValidHeader(data []byte) bool

ValidHeader checks whether data is a correct xz file header. The length of data must be HeaderLen.

Types

type Block

type Block struct {
	Offset             int64 // Absolute offset of the compressed block within the file
	CompressedSize     int64 // Size of the compressed block including block header and padding
	UncompressedOffset int64 // Absolute offset of the block's uncompressed data within the stream
	UncompressedSize   int64 // Uncompressed size of the block data
	StreamFlags        byte  // Checksum type (flags) from the stream header needed to decode the block
}

Block represents the location and metadata of a single XZ block within a file.

func ParseBlocks

func ParseBlocks(r io.ReaderAt, size int64) ([]Block, error)

ParseBlocks scans an XZ file from the end to extract the boundaries of all blocks. It requires an io.ReaderAt and the total size of the file to parse the backward-linked indexes. This allows O(1) seeking and parallel decompression of blocks.

type ParallelReader

type ParallelReader struct {
	// contains filtered or unexported fields
}

ParallelReader provides multi-core decompression of XZ files. It requires the input to implement io.ReaderAt to parse the backward-linked block index.

func (*ParallelReader) Close

func (pr *ParallelReader) Close() error

Close aborts any pending decompression tasks and frees resources.

func (*ParallelReader) Read

func (pr *ParallelReader) Read(p []byte) (int, error)

Read decompressed data sequentially.

type Reader

type Reader struct {
	ReaderConfig
	// contains filtered or unexported fields
}

Reader supports the reading of one or multiple xz streams.

Example
package main

import (
	"bufio"
	"io"
	"log"
	"os"

	"github.com/unxed/xz"
)

func main() {
	f, err := os.Open("fox.xz")
	if err != nil {
		log.Fatalf("os.Open(%q) error %s", "fox.xz", err)
	}
	defer f.Close()
	r, err := xz.NewReader(bufio.NewReader(f))
	if err != nil {
		log.Fatalf("xz.NewReader(f) error %s", err)
	}
	if _, err = io.Copy(os.Stdout, r); err != nil {
		log.Fatalf("io.Copy error %s", err)
	}
}
Output:
The quick brown fox jumps over the lazy dog.

func NewReader

func NewReader(xz io.Reader) (r *Reader, err error)

NewReader creates a new xz reader using the default parameters. The function reads and checks the header of the first XZ stream. The reader will process multiple streams including padding.

func (*Reader) Read

func (r *Reader) Read(p []byte) (n int, err error)

Read reads uncompressed data from the stream.

type ReaderConfig

type ReaderConfig struct {
	DictCap      int
	SingleStream bool
}

ReaderConfig defines the parameters for the xz reader. The SingleStream parameter requests the reader to assume that the underlying stream contains only a single stream.

func (ReaderConfig) NewBlockReader

func (c ReaderConfig) NewBlockReader(r io.Reader, streamFlags byte) (io.Reader, error)

NewBlockReader creates a new reader for a single XZ block. The provided io.Reader must be positioned exactly at the start of the block header (Block.Offset). The streamFlags byte specifies the checksum type, which must be obtained from the stream header or ParseBlocks index.

func (ReaderConfig) NewParallelReader

func (c ReaderConfig) NewParallelReader(r io.ReaderAt, size int64) (*ParallelReader, error)

NewParallelReader creates a new ParallelReader that decompresses independent blocks concurrently using a worker pool. This provides near-linear scaling with available CPU cores.

func (ReaderConfig) NewReader

func (c ReaderConfig) NewReader(xz io.Reader) (r *Reader, err error)

NewReader creates an xz stream reader. The created reader will be able to process multiple streams and padding unless a SingleStream has been set in the reader configuration c.

func (*ReaderConfig) Verify

func (c *ReaderConfig) Verify() error

Verify checks the reader parameters for Validity. Zero values will be replaced by default values.

type Writer

type Writer struct {
	WriterConfig
	// contains filtered or unexported fields
}

Writer compresses data written to it. It is an io.WriteCloser.

Example
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/unxed/xz"
)

func main() {
	f, err := os.Create("example.xz")
	if err != nil {
		log.Fatalf("os.Open(%q) error %s", "example.xz", err)
	}
	defer f.Close()
	w, err := xz.NewWriter(f)
	if err != nil {
		log.Fatalf("xz.NewWriter(f) error %s", err)
	}
	defer w.Close()
	_, err = fmt.Fprintln(w, "The brown fox jumps over the lazy dog.")
	if err != nil {
		log.Fatalf("fmt.Fprintln error %s", err)
	}
	if err = w.Close(); err != nil {
		log.Fatalf("w.Close() error %s", err)
	}
}

func NewWriter

func NewWriter(xz io.Writer) (w *Writer, err error)

NewWriter creates a new xz writer using default parameters.

func (*Writer) Close

func (w *Writer) Close() error

Close closes the writer and adds the footer to the Writer. Close doesn't close the underlying writer.

func (*Writer) Write

func (w *Writer) Write(p []byte) (n int, err error)

Write compresses the uncompressed data provided.

type WriterConfig

type WriterConfig struct {
	Properties *lzma.Properties
	DictCap    int
	BufSize    int
	BlockSize  int64
	// checksum method: CRC32, CRC64 or SHA256 (default: CRC64)
	CheckSum byte
	// Forces NoChecksum (default: false)
	NoCheckSum bool
	// match algorithm
	Matcher lzma.MatchAlgorithm
}

WriterConfig describe the parameters for an xz writer.

func (WriterConfig) NewWriter

func (c WriterConfig) NewWriter(xz io.Writer) (w *Writer, err error)

NewWriter creates a new Writer using the given configuration parameters.

func (*WriterConfig) Verify

func (c *WriterConfig) Verify() error

Verify checks the configuration for errors. Zero values will be replaced by default values.

Directories

Path Synopsis
cmd
gxz command
Command gxz supports the compression and decompression of LZMA files.
Command gxz supports the compression and decompression of LZMA files.
xb command
Command xb supports the xz for Go project builds.
Command xb supports the xz for Go project builds.
internal
gflag
Package gflag implements GNU-style command line flag parsing.
Package gflag implements GNU-style command line flag parsing.
hash
Package hash provides rolling hashes.
Package hash provides rolling hashes.
randtxt
Package randtxt supports the generation of random text using a trigram model for the English language.
Package randtxt supports the generation of random text using a trigram model for the English language.
term
Package term provides the IsTerminal function.
Package term provides the IsTerminal function.
xlog
Package xlog provides a simple logging package that allows to disable certain message categories.
Package xlog provides a simple logging package that allows to disable certain message categories.
Package lzma supports the decoding and encoding of LZMA streams.
Package lzma supports the decoding and encoding of LZMA streams.
Package xio provides tools to handle I/O operations.
Package xio provides tools to handle I/O operations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL