Skip to content

Quickstart

Python

Write a .bz2 file with the standard library's bz2, to have one to read:

import bz2

with bz2.open("sample.bz2", "wb") as f:
    for i in range(10_000):
        f.write(f"line {i}\n".encode())

A whole file in memory, decoded on every CPU this process may use, or on one thread:

>>> import mibz2
>>> compressed = open("sample.bz2", "rb").read()
>>> data = mibz2.decompress(compressed)
>>> data == bz2.decompress(compressed)
True
>>> mibz2.decompress(compressed, threads=1) == data
True

A file read as it is decoded: open takes a path or a binary file object, and returns a buffered binary file. Its raw.verified turns true once a read has reached the end with every block's and stream's CRC matched:

>>> with mibz2.open("sample.bz2") as f:
...     first = f.readline()
...     before = f.raw.verified
...     rest = f.read()
...     after = f.raw.verified
>>> first, before, after
(b'line 0\n', False, True)

A bad input raises mibz2.DecodeError, a ValueError, from decompress or from the read at which it is found. The message says which block and bit decoding failed at:

>>> damaged = bytearray(compressed)
>>> damaged[len(damaged) // 2] ^= 0x10
>>> try:
...     mibz2.decompress(bytes(damaged))
... except mibz2.DecodeError as e:
...     print(type(e).__name__, isinstance(e, ValueError))
DecodeError True

Rust

use std::io::Read;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // a whole .bz2 in memory (its streams one after another): on this thread, or on 4
    let data = std::fs::read("file.bz2")?;
    let text = mibz2::decode(&data)?;
    let same = mibz2::decode_parallel(&data, 4)?;
    assert_eq!(text, same);

    // any Read, as a Read: on this thread, or block-parallel on 4 worker threads
    let mut out = Vec::new();
    mibz2::BzReader::parallel(std::fs::File::open("file.bz2")?, 4).read_to_end(&mut out)?;
    Ok(())
}

A bad stream is an mibz2::Error (its kind, block and bit), or from a BzReader an io::Error of kind InvalidData wrapping it. The Rust reference lists the rest: the push decoder, the block scanner and the decoding of a range of blocks.