A header only library to read and write compressed files using a standard streams interface
  • C++ 91.2%
  • CMake 8.8%
Find a file
Maarten L. Hekkelman c88f5f585d
All checks were successful
test on FreeBSD / build (Release, c++, freebsd-latest) (push) Successful in 22s
test on Debian / build (Release, g++, debian-latest) (push) Successful in 3m27s
Update README
2026-05-12 16:25:59 +02:00
.forgejo/workflows Remove warnings 2026-05-12 16:22:57 +02:00
.github Update README 2026-05-12 16:25:59 +02:00
cmake Replace pkg-config with proper FindLibLZMA 2022-08-15 09:07:27 +02:00
example Complete 2022-08-13 15:43:15 +02:00
include Remove warnings 2026-05-12 16:22:57 +02:00
test Remove warnings 2026-05-12 16:22:57 +02:00
.clang-format Remove warnings 2026-05-12 16:22:57 +02:00
.gitattributes For Win 2022-11-10 16:55:44 +01:00
.gitignore First check in 2022-08-13 14:52:45 +02:00
changelog version bump 2026-05-12 16:23:44 +02:00
CMakeLists.txt version bump 2026-05-12 16:23:44 +02:00
LICENSE_1_0.txt Added missing license 2022-08-13 15:47:46 +02:00
README.md Update README 2026-05-12 16:25:59 +02:00

github CI github CI

About gxrio

For years I've been writing code that used boost::iostreams only to transparently support gzipped files as input. But the dependency on boost::iostreams proved to be a source of confusion and errors. Mostly due to the fact that using statically linked boost libraries also need to link to zlib.

And like I said, I only need the gzip functionality. So I took a day off to write my own stream classes. But when I was done, I realised gzip is perhaps no longer hippest kid in town and xz looked like a nice alternative. Fortunately, the API was rather similar and so I created both implementations.

To make life easier, there now is a generic gxrio::istream class that can read files compressed with gzip and xz but also uncompressed files. It does this by inspecting the first few bytes of an input stream (the signature) and decide what algorith to use based on that.

Installation

This library is a header only library. No need to compile anything. Unless you want to run the unit-tests of course.

So building and installing is a simple as:

cmake . # (optionally providing e.g. -DCMAKE_INSTALL_PREFIX=$HOME/.local )
cmake --build .
cmake --install .

Usage

The goal was to have simple replacements for std::istream and std::ifstream that read from gzipped files and deflate them on the fly, transparently. And of course the same for the output variants.

Note that due to the nature of compressed files, there is no way to seek in opened streams. Allthough, if anyone can convince me I might add that since the zlib implementation seems to have support for this.

Opening a file for reading is as simple as:

#include <iostream>
#include <gxrio.hpp>

int main(int argc, char * const argv[])
{
	gxrio::ifstream in(argv[1]);

	if (not in.is_open())
	{
		std::cerr << "Could not open file" << std::endl;
		exit(1);
	}

	std::string line;
	while (getline(in, line))
		std::cout << line << std::endl;

	return 0;
}

This will work on regular files, files compressed with gzip and file compressed with xz.

You can also use another buffer as input, as in this example:

	unsigned char kGZippedData[] = {
		0x1f, 0x8b, 0x08, 0x08, 0x61, 0xb2, 0xf0, 0x62, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
		0x78, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0x51,
		0xe4, 0x02, 0x00, 0x18, 0xa7, 0x55, 0x7b, 0x0e, 0x00, 0x00, 0x00
	};

	struct membuf : public std::streambuf
	{
		membuf(char *text, size_t length)
		{
			this->setg(text, text, text + length);
		}
	} buffer(reinterpret_cast<char *>(kGZippedData), sizeof(kGZippedData));

	gxrio::istream in(&buffer);

Writing is similar, however, having a gxrio::ostream class is not very useful. It won't know what to do. But a gxrio::ofstream class is provided, it will decide what compression to use based on the filename extension. So, writing becomes as simple as:

	gxrio::ofstream out("hello.xz");
	out << "Hello, world!" << std::endl;
	out.close();