github.com/weirdbricks/bz2.cr
0.1.0 / published Aug 3, 2026 / repository
Crystal bindings to the bzip2 (libbz2) compression library
bz2.cr
Crystal bindings to bzip2's libbz2 - a
real, write-only/read-only IO pair (Compress::BZ2::Writer /
Compress::BZ2::Reader) backed by the same C library the bzip2 CLI
itself uses, in the same shape as Crystal's own stdlib Compress::Gzip.
Why
Crystal's standard library ships native Compress::Gzip/Compress::Zip,
and naqvis/xz.cr already covers xz/
lzma with a real liblzma binding - but bzip2 had nothing: the only prior
shard to turn up in a search was a 2017, read-only wrapper that shells out
to the bzcat binary internally, not a real implementation. libbz2
itself is a small, extremely stable C library (unchanged since 1996, the
same one Python's own bz2 module binds to), so writing a proper binding
was straightforward.
Credit
This shard's structure - the lib binding layout, the Writer/Reader
class shapes, the buffered-peek decompression loop - is modeled directly
on naqvis/xz.cr by Ali Naqvi.
bzip2's bz_stream C API is close enough in shape to lzma's lzma_stream
that most of xz.cr's design translates over with only small adjustments
(bzlib's simpler action/return-code model, no filter chains or presets
beyond a 1-9 block size). Thanks also to
naqvis/crystar for being the
pure-Crystal tar library this was originally paired with in
crystal-ansible, which
is what prompted this shard's existence.
Installation
Add this to your shard.yml:
dependencies:
bz2:
github: weirdbricks/bz2.cr
Requires libbz2-dev (or equivalent) at build time for bzlib.h and
libbz2.so; only the runtime libbz2 shared library is needed at
runtime, and it's present on essentially every Linux distribution and
macOS by default.
Usage
require "bz2"
# Compress
File.open("file.txt", "r") do |input_file|
File.open("file.bz2", "w") do |output_file|
Compress::BZ2::Writer.open(output_file) do |bz2|
IO.copy(input_file, bz2)
end
end
end
# Decompress
File.open("file.bz2") do |file|
Compress::BZ2::Reader.open(file) do |bz2|
puts bz2.gets_to_end
end
end
Writer.new/.open accept block_size100k (1..9, default 9 - matches
bzip2's own default of maximum compression) and work_factor (0..250,
default 0, meaning bzlib's own default of 30 - only affects behavior on
highly repetitive worst-case input, never the decompressor).
License
MIT