An open API service indexing awesome lists of open source software.

https://github.com/rikyoz/bit7z

A C++ static library offering a clean and simple interface to the 7-zip shared libraries.
https://github.com/rikyoz/bit7z

7-zip 7z 7zip archives archives-metadata bzip2 c-plus-plus compression cpp cpp-library cross-platform encrypted-archives extraction gzip in-memory multi-volume-archives rar static-library tar zip

Last synced: 19 days ago
JSON representation

A C++ static library offering a clean and simple interface to the 7-zip shared libraries.

Awesome Lists containing this project

README

        

bit7z

A C++ static library offering a clean and simple interface to the 7-Zip shared libraries.


Supported Features
Getting Started
Download
Requirements
Installation
Configuration
Donate
License


GitHub releaseC++14WindowsLinuxmacOSBSDx86, x64, arm, arm64donatedocsBuild status


MSVC 2015+GCC 4.9+Clang 3.6+CodeFactor GradeLicense

## ⚡️ Introduction

**bit7z** is a _cross-platform_ C++ static library that allows the _compression/extraction of archive files_ through a _clean_ and _simple_ wrapper interface to the dynamic libraries from the [7-Zip](https://www.7-zip.org/ "7-Zip Project Homepage") project.

It supports compression and extraction to and from the filesystem or the memory, reading archives metadata, updating existing ones, creating multi-volume archives, operation progress callbacks, and many other functionalities.

## 🎯 Supported Features

+ **Compression** using the following archive formats: **7z**, XZ, **BZIP2**, **GZIP**, TAR, **ZIP**, and WIM.
+ **Extraction** of many archive formats: **7z**, AR, ARJ, **BZIP2**, CAB, CHM, CPIO, CramFS, DEB, DMG, EXT, FAT, GPT, **GZIP**, HFS, HXS, IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, **RAR**, **RAR5**, RPM, SquashFS, TAR, UDF, UEFI, VDI, VHD, VMDK, WIM, XAR, XZ, Z, and **ZIP**.
+ **Reading metadata** of archives and their content.
+ **Testing** archives for errors.
+ **Updating** existing file archives with new files.
+ **Renaming**, **updating**, or **deleting** old items in existing file archives.
+ **Compression and extraction _to and from_ memory** and **C++ standard streams**.
+ Compression using **custom path aliases** for the items in the output archives.
+ **Selective extraction** of only specified files/folders **using wildcards** and **regular expressions**.
+ Creation of **encrypted archives** (strong AES-256 encryption; only for 7z and ZIP formats).
+ **Archive header encryption** (only for 7z format).
+ Possibility to choose the **compression level** (if supported by the archive format), the **compression method** ([supported methods](https://github.com/rikyoz/bit7z/wiki/Advanced-Usage#compression-methods "Wiki page on bit7z's supported compression methods")), the **dictionary size**, and the **word size**.
+ **Automatic input archive format detection**.
+ **Solid archives** (only for 7z).
+ **Multi-volume archives**.
+ **Operation callbacks** for obtaining real-time information about ongoing operations.
+ **Canceling** or **pausing** the current operation.

> [!NOTE]
>
> The presence or not of some of the above features depends on the specific 7-Zip shared library used.
>
> For example, 7z.dll should support all these features, 7za.dll should work only with the 7z file format, and 7zxa.dll can only extract 7z files.
>
> For more information about the 7-Zip DLLs, please check this [wiki page](https://github.com/rikyoz/bit7z/wiki/7z-DLLs).

> [!NOTE]
>
> Some features (e.g., _automatic format detection_ and _selective extraction using regular expressions_) are disabled by default, and macro definitions must be used during compilation to have them available ([wiki](https://github.com/rikyoz/bit7z/wiki/Building-the-library)).

## 🔥 Getting Started (Library Usage)

Below are a few examples that show how to use some of the main features of bit7z.

### 📂 Extracting Files from an Archive

```cpp
#include

try { // bit7z classes can throw BitException objects
using namespace bit7z;

Bit7zLibrary lib{ "7za.dll" };
BitFileExtractor extractor{ lib, BitFormat::SevenZip };

// Extracting a simple archive
extractor.extract( "path/to/archive.7z", "out/dir/" );

// Extracting a specific file inside an archive
extractor.extractMatching( "path/to/archive.7z", "file.pdf", "out/dir/" );

// Extracting the first file of an archive to a buffer
std::vector< byte_t > buffer;
extractor.extract( "path/to/archive.7z", buffer );

// Extracting an encrypted archive
extractor.setPassword( "password" );
extractor.extract( "path/to/another/archive.7z", "out/dir/" );
} catch ( const bit7z::BitException& ex ) { /* Do something with ex.what()...*/ }
```

Alternatively, if you only need to work on a single archive:

```cpp
#include

try { // bit7z classes can throw BitException objects
using namespace bit7z;

Bit7zLibrary lib{ "7z.dll" };

// Opening the archive
BitArchiveReader archive{ lib, "path/to/archive.gz", BitFormat::GZip };

// Testing the archive
archive.test();

// Extracting the archive
archive.extractTo( "out/dir/" );
} catch ( const bit7z::BitException& ex ) { /* Do something with ex.what()...*/ }
```

### 💼 Compressing Files into an Archive

```cpp
#include

try { // bit7z classes can throw BitException objects
using namespace bit7z;

Bit7zLibrary lib{ "7z.dll" };
BitFileCompressor compressor{ lib, BitFormat::Zip };

std::vector< std::string > files = { "path/to/file1.jpg", "path/to/file2.pdf" };

// Creating a simple zip archive
compressor.compress( files, "output_archive.zip" );

// Creating a zip archive with a custom directory structure
std::map< std::string, std::string > files_map = {
{ "path/to/file1.jpg", "alias/path/file1.jpg" },
{ "path/to/file2.pdf", "alias/path/file2.pdf" }
};
compressor.compress( files_map, "output_archive2.zip" );

// Compressing a directory
compressor.compressDirectory( "dir/path/", "dir_archive.zip" );

// Creating an encrypted zip archive of two files
compressor.setPassword( "password" );
compressor.compressFiles( files, "protected_archive.zip" );

// Updating an existing zip archive
compressor.setUpdateMode( UpdateMode::Append );
compressor.compressFiles( files, "existing_archive.zip" );

// Compressing a single file into a buffer
std::vector< bit7z::byte_t > buffer;
BitFileCompressor compressor2{ lib, BitFormat::BZip2 };
compressor2.compressFile( files[0], buffer );
} catch ( const bit7z::BitException& ex ) { /* Do something with ex.what()...*/ }
```

Alternatively, if you only need to work on a single archive:

```cpp
#include

try { // bit7z classes can throw BitException objects
using namespace bit7z;

Bit7zLibrary lib{ "7z.dll" };
BitArchiveWriter archive{ lib, BitFormat::SevenZip };

// Adding the items to be compressed (no compression is performed here)
archive.addFile( "path/to/file.txt" );
archive.addDirectory( "path/to/dir/" );

// Compressing the added items to the output archive
archive.compressTo( "output.7z" );
} catch ( const bit7z::BitException& ex ) { /* Do something with ex.what()...*/ }
```

### 📑 Reading Archive Metadata

```cpp
#include

try { // bit7z classes can throw BitException objects
using namespace bit7z;

Bit7zLibrary lib{ "7za.dll" };
BitArchiveReader arc{ lib, "archive.7z", BitFormat::SevenZip };

// Printing archive metadata
std::cout << "Archive properties\n";
std::cout << " Items count: " << arc.itemsCount() << '\n';
std::cout << " Folders count: " << arc.foldersCount() << '\n';
std::cout << " Files count: " << arc.filesCount() << '\n';
std::cout << " Size: " << arc.size() <<'\n';
std::cout << " Packed size: " << arc.packSize() << "\n\n";

// Printing the metadata of the archived items
std::cout << "Archived items";
for ( const auto& item : arc ) {
std::cout << '\n';
std::cout << " Item index: " << item.index() << '\n';
std::cout << " Name: " << item.name() << '\n';
std::cout << " Extension: " << item.extension() << '\n';
std::cout << " Path: " << item.path() << '\n';
std::cout << " IsDir: " << item.isDir() << '\n';
std::cout << " Size: " << item.size() << '\n';
std::cout << " Packed size: " << item.packSize() << '\n';
std::cout << " CRC: " << std::hex << item.crc() << std::dec << '\n';
}
std::cout.flush();
} catch ( const bit7z::BitException& ex ) { /* Do something with ex.what()...*/ }
```

A complete _**API reference**_ is available in the [wiki](https://github.com/rikyoz/bit7z/wiki/) section.

### 🚀 Upgrading from bit7z v3 to v4

The newest bit7z v4 introduced some significant breaking changes to the library's API.

Expand for more details!

+ By default, the project now follows the [UTF-8 Everywhere Manifesto](http://utf8everywhere.org/):
+ The default string type is `std::string` (instead of `std::wstring`), so users can use the library in cross-platform projects more easily (v4 introduced Linux/macOS support too).
+ Input `std::string`s will be considered as UTF-8 encoded.
+ You can still achieve the old behavior on Windows using the `-DBIT7Z_USE_NATIVE_STRING` CMake option.
+ The old `BitExtractor` class is now called `BitFileExtractor`.
+ Now `BitExtractor` is just the name of a template class for all the extraction classes.
+ The old `BitCompressor` class is now called `BitFileCompressor`.
+ Now `BitCompressor` is just the name of a template class for all the compression classes.
+ The old `BitArchiveInfo` class is now called `BitArchiveReader`, and it allows to extract single archives.
+ The `ProgressCallback` now must return a `bool` value indicating whether the current operation can continue (`true`) or not (`false`).
+ The `BitException` class now inherits from `std::system_error` rather than `std::runtime_error`.

+ The method `BitException::getErrorCode()` was renamed `BitException::hresultCode()`.
+ The project structure changed:
+ Public API headers moved from `include/` to the `include/bit7z/` folder, so `#include` directives now need to prepend `bit7z/` to the included header name (e.g., `#include `).
+ Even though it is a bit verbose, it is a typical structure for C and C++ libraries, and it makes explicit which third-party library a header file belongs to.
+ By default, the output folder of bit7z is now `lib//`; if the CMake generator is multi-config (e.g., Visual Studio generators), the default output folder is `lib///`.
+ Optionally, you can force using the "Visual Studio style" output path by enabling the `BIT7Z_VS_LIBNAME_OUTDIR_STYLE` CMake option.
+ Third-party dependencies are no longer handled using git submodules but are automatically downloaded using [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake) when configuring/using the library via CMake.

## 💾 Download


GitHub Latest Release



GitHub All Releases

Each released package contains:

+ A _pre-compiled version_ of bit7z (both in _debug_ and _release_ mode);
+ The _public API headers_ needed to use the library in your program;

Packages are available for both _x86_ and _x64_ architectures.

You can also clone/download this repository and build the library yourself (please, read the [wiki](https://github.com/rikyoz/bit7z/wiki/Building-the-library)).

## 🧰 Requirements

+ **Operating System:** Windows, Linux, macOS, Android.
+ **Architecture:** x86, x86_64, arm, arm64.
+ **Language Standard:** C++11 (for using the library), C++14 (for building the library).
+ **Compiler:** MSVC 2015 or later[^1], MinGW v6.4 or later, GCC v4.9 or later, Clang 3.6 or later.
+ **Shared Library:** a 7-Zip `.dll` library on Windows, a 7-Zip/p7zip `.so` library on Unix.

> [!NOTE]
>
> + **RAR Archive Support:** The library supports RAR archives *only* when using 7-Zip's `7z.dll`/`7z.so`. It doesn't support p7zip's unrar plugin. For RAR extraction on Unix-based systems, you need to build the 7-Zip `7z.so` library.
> + **7-Zip Libraries:** Bit7z does **not** ship with the 7-Zip shared libraries. You can download the precompiled binaries or build them from the source at [7-zip.org](https://www.7-zip.org/).

[^1]: MSVC 2010 was supported until v2.x, MSVC 2012/2013 until v3.x.

## 🔗 Installation

The library can be installed as a dependency of your project in a number of different ways:

### Using CMake's `add_subdirectory`

You can directly integrate the library into your CMake project:

+ Either download bit7z's sources to a sub-directory of your project (e.g., `third_party`), or add this repository as a git submodule of yours.
+ Then, use the command `add_subdirectory()` in your `CMakeLists.txt` to include bit7z.
+ Finally, link the `bit7z` library using the `target_link_libraries()` command.

For example:

```cmake
add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/bit7z) # Path to bit7z's repository
# Here you can enable/disable bit7z's build options, e.g.:
# set(BIT7Z_USE_NATIVE_STRING ON CACHE BOOL "enable using native OS strings" FORCE)
target_link_libraries(${YOUR_TARGET} PRIVATE bit7z)
```

### Using [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake)

```cmake
CPMAddPackage("gh:rikyoz/bit7z@") # Replace with the desired one.
# Here you can enable/disable bit7z's build options, e.g.:
# set(BIT7Z_AUTO_FORMAT ON CACHE BOOL "enable auto format support" FORCE)
target_link_libraries(${YOUR_TARGET} PRIVATE bit7z)
```

### Using [vcpkg](https://vcpkg.io/en/)

First, you need to install the library:

```cmd
vcpkg install bit7z
```

Then, you add bit7z as a dependency in your project's `CMakeLists.txt`:

```cmake
find_package(unofficial-bit7z CONFIG REQUIRED)
target_link_libraries(${YOUR_TARGET} PRIVATE unofficial::bit7z::bit7z64)
```

### Building from source and manually linking

The wiki provides instructions on how to [build](https://github.com/rikyoz/bit7z/wiki/Building-the-library) the library from the source code and [manually link](https://github.com/rikyoz/bit7z/wiki/Installing-the-library#manually-linking) it into your project.

## 🛠️ Configuration

The library is highly customizable: for a detailed list of the available build options, please refer to the [wiki](https://github.com/rikyoz/bit7z/wiki/Build-options).

### 📌 7-Zip Version

While configuring bit7z via CMake, it automatically downloads the latest version of 7-Zip supported by the library.

Optionally, you can specify a different version of 7-Zip via the CMake option `BIT7Z_7ZIP_VERSION` (e.g., `-DBIT7Z_7ZIP_VERSION="22.01"`).

Alternatively, you can specify a custom path containing the 7-Zip source code via the option `BIT7Z_CUSTOM_7ZIP_PATH`.

> [!NOTE]
>
> In general, it is best to use the same version of 7-Zip of the shared libraries that you will use at runtime.
>

#### Using 7-Zip v23.01 on Linux and macOS

By default, bit7z is compatible with the `7z.so` from 7-Zip v23.01 and later.

If you plan to use the `7z.so` from p7zip or 7-Zip v22.01 and earlier instead, you have two ways to make bit7z compatible:

+ Configure bit7z with the CMake option `-DBIT7Z_USE_LEGACY_IUNKNOWN=ON`; _or_
+ Configure bit7z for 7-Zip v22.01 (i.e., `-DBIT7Z_7ZIP_VERSION="22.01"`).

Expand for more details
_On Linux and macOS_, 7-Zip v23.01 introduced breaking changes to the IUnknown interface.
As a result, if you build bit7z for such a version of 7-Zip (the default), it will not support using the shared libraries from previous versions of 7-Zip (or from p7zip).
Conversely, bit7z made for earlier versions of 7-Zip or for p7zip is incompatible with the shared libraries from 7-Zip v23.01 and later.

You can build the shared libraries of 7-Zip v23.01 in a backward-compatible mode by defining the macro `Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN`.
If this is your case, you'll need to enable the `BIT7Z_USE_LEGACY_IUNKNOWN` to make bit7z work (in this case, bit7z will be compatible also with previous versions of 7-Zip/p7zip).

### 🗺️ String Encoding

By default, bit7z follows the [UTF-8 Everywhere Manifesto](http://utf8everywhere.org/) to simplify the use of the library within cross-platform projects.
In short, this means that:

+ The default path string type is `std::string`.
+ Input `std::string`s are considered as UTF-8 encoded; output `std::string`s are UTF-8 encoded.

Expand for more details and for other string encoding options!

On POSIX systems, `std::string`s are usually already UTF-8 encoded, and no configuration is needed.

The situation is a bit more complex on Windows since, by default, Windows treats `std::string`s as encoded using the system code page, which may not necessarily be UTF-8, like, for example, [Windows-1252](https://en.wikipedia.org/wiki/Windows-1252).

If your program deals exclusively with ASCII-only strings, you should be fine with the default bit7z settings (as ASCII characters are also UTF-8).

However, if you need to handle non-ASCII/Unicode characters, as it is likely, you have the following options:

+ Enforcing using the UTF-8 code page for your whole application, as explained by Microsoft [here](https://learn.microsoft.com/en-us/windows/apps/design/globalizing/use-utf8-code-page):
+ _**Recommended**_, but supported only since Windows 10 1903 and later.
+ Manually ensuring the encoding of the `std::string`s passed to bit7z:
+ You can use some string encoding library or C++11's UTF-8 string literals for input strings.
+ User-input strings (e.g., the password of an archive) can be handled as explained [here](https://nullprogram.com/blog/2020/05/04/); in short: read the input as an UTF-16 wide string (e.g., via `ReadConsoleW`), and convert it to UTF-8 (bit7z provides a utility function for this, `bit7z::to_tstring`).
+ You can correctly print the UTF-8 output strings from bit7z (e.g., the path/name metadata of a file in an archive) to the console by calling [`SetConsoleOutputCP(CP_UTF8)`](https://learn.microsoft.com/en-us/windows/console/setconsoleoutputcp) before.
+ Configuring bit7z to use UTF-16 encoded wide strings (i.e., `std::wstring`) by enabling the `BIT7Z_USE_NATIVE_STRING` option via CMake.
+ If your program is Windows-only, or you already use wide strings on Windows, this might be the best choice since it will avoid any internal string conversions (7-Zip always uses wide strings).
+ This option makes developing cross-platform applications slightly inconvenient since you'll still have to use `std::string` on POSIX systems.
+ The library provides a type alias `bit7z::tstring` and a macro function `BIT7Z_STRING` for defining wide string variables and literals on Windows and narrow ones on other platforms.
+ You must programmatically set the standard input and output encoding to UTF-16 to correctly read and print Unicode characters:

```cpp
#include //for _O_U16TEXT
#include //for _setmode

_setmode(_fileno(stdout), _O_U16TEXT); // setting the stdout encoding to UTF16
_setmode(_fileno(stdin), _O_U16TEXT); // setting the stdin encoding to UTF16
```

+ Configuring bit7z to use the system code page encoding for `std::string` by enabling the `BIT7Z_USE_SYSTEM_CODEPAGE` option via CMake.
+ _Not recommended_: using this option, your program will be limited in the set of characters it can pass to and read from bit7z.

## ☕️ Donate

If you have found this project helpful, please consider supporting me with a small donation so that I can keep improving it!
Thank you! :pray:


Sponsor me on GitHubBuy Me a Coffee at ko-fi.comDonations

## 📜 License

This project is licensed under the terms of the [Mozilla Public License v2.0](https://www.mozilla.org/en-US/MPL/2.0/).

For more details, please check:

+ The [LICENSE](./LICENSE) file.
+ [Mozilla's MPL-2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/)

Older versions (v3.x and earlier) of bit7z were released under the [GNU General Public License v2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).




Copyright © 2014 - 2024 Riccardo Ostani (@rikyoz)