介紹如何在 C++ 程式中使用 Boost 函式庫的 gzip filter 進行串流資料的壓縮與解壓縮。
安裝 Boost 函式庫
在 Ubuntu Linux 中可以直接使用 apt 安裝 Boost 函式庫。安裝時可以將整套 Boost 的所有元件一次裝好:
# 安裝所有 Boost 套件
sudo apt install libboost-all-dev
或是只裝我們需要的元件:
# 安裝 Boost 套件的 iostreams 元件
sudo apt install libboost-iostreams-dev
Gzip 壓縮
這是將資料以 gzip 壓縮之後,將串流轉送至 std::cout 的例子。
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
int main() {
// 將檔案以串流方式開啟
std::ifstream file("data.txt", std::ios_base::in | std::ios_base::binary);
// 建立 Filter Chain
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
// 加入 Gzip 壓縮 filter
in.push(boost::iostreams::gzip_compressor());
// 加入資料來源
in.push(file);
// 將 in 串流導入 std::cout
boost::iostreams::copy(in, std::cout);
}
使用 g++ 指令編譯程式:
# 編譯程式
g++ compress.cpp -o compress -lboost_iostreams
若要以 CMake 編譯,可以搭配以下這個 CMakeLists.txt 設定檔:
cmake_minimum_required(VERSION 3.8)
# 設定專案名稱
project(Compress)
# 尋找並引入 Boost 函式庫的指定元件
find_package(Boost 1.56 REQUIRED COMPONENTS iostreams)
# 增加一個執行檔
add_executable(compress compress.cpp)
# 定義執行檔連結方式
target_link_libraries(compress Boost::iostreams)
Gzip 串流壓縮
這是一個以 filtering_ostream 串流來進行 gzip 壓縮的範例,適用於大量資料的壓縮,其編譯方式跟上一個例子完全相同。
#include <iostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
int main() {
// 建立 Filter Chain
boost::iostreams::filtering_ostream out;
// 加入 Gzip 壓縮 filter
out.push(boost::iostreams::gzip_compressor());
// 加入 File Sink
out.push(boost::iostreams::file_sink("data.gz"));
// 輸入資料
out << "Hello, Boost!";
// 關閉串流
boost::iostreams::close(out);
return 0;
}
Gzip 解壓縮
這是將 gzip 壓縮的資料解壓縮之後,將串流轉送至 std::cout 的例子。
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
int main() {
// 將檔案以串流方式開啟
std::ifstream file("data.gz", std::ios_base::in | std::ios_base::binary);
// 建立 Filter Chain
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
// 加入 Gzip 解壓縮 filter
in.push(boost::iostreams::gzip_decompressor());
// 加入資料來源
in.push(file);
// 將 in 串流導入 std::cout
boost::iostreams::copy(in, std::cout);
}
使用 g++ 指令編譯程式:
# 編譯程式
g++ uncompress.cpp -o uncompress -lboost_iostreams
若要以 CMake 編譯,可以搭配以下這個 CMakeLists.txt 設定檔:
cmake_minimum_required(VERSION 3.8)
# 設定專案名稱
project(UnCompress)
# 尋找並引入 Boost 函式庫的指定元件
find_package(Boost 1.56 REQUIRED COMPONENTS iostreams)
# 增加一個執行檔
add_executable(uncompress uncompress.cpp)
# 定義執行檔連結方式
target_link_libraries(uncompress Boost::iostreams)
Gzip 串流解壓縮
這是一個以 filtering_ostream 串流來進行 gzip 解壓縮的範例,適用於大量資料的解壓縮,其編譯方式也都相同。
#include <iostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
int main() {
// 原始壓縮資料
int size = 1024;
char* memblock = new char [size];
// 建立 Filter Chain
boost::iostreams::filtering_ostream out;
// 加入 Gzip 解壓縮 filter
out.push(boost::iostreams::gzip_decompressor());
// 加入 File Sink
out.push(boost::iostreams::file_sink("data.txt"));
// 輸入資料
out.write(memblock, size);
// 關閉串流
boost::iostreams::close(out);
delete[] memblock;
return 0;
}
Gzip 壓縮字串
這一個簡單的 Gzip 類別可以用來對字串進行壓縮與解壓縮。
#include <sstream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
class Gzip {
public:
static std::string compress(const std::string& data) {
namespace bio = boost::iostreams;
std::stringstream compressed;
std::stringstream origin(data);
bio::filtering_streambuf<bio::input> out;
out.push(bio::gzip_compressor(bio::gzip_params(bio::gzip::best_compression)));
out.push(origin);
bio::copy(out, compressed);
return compressed.str();
}
static std::string decompress(const std::string& data) {
namespace bio = boost::iostreams;
std::stringstream compressed(data);
std::stringstream decompressed;
bio::filtering_streambuf<bio::input> out;
out.push(bio::gzip_decompressor());
out.push(compressed);
bio::copy(out, decompressed);
return decompressed.str();
}
};
使用這個 Gzip 類別時,編譯也要加上 -lboost_iostreams 參數。
