lzh_file_source (圧縮版)
ようやくLZHデコード処理を組み込みました。
対応ヘッダはLevel 0〜2で、圧縮方法はlh4〜lh7をサポートしています。
<hamigaki/iostreams/filter/sliding_window.hpp>
<hamigaki/iostreams/filter/lzhuff.hpp>
lzh_file.hppの差分
性能を測るため、23MBの適当なLZHファイルの展開速度を計測してみました。
ツール | 時間 |
---|---|
UNLHA32.DLL | 5秒 |
lzh_file_source | 33秒 |
破滅的に遅いですね。
Cygwinでプロファイリングしてみたところ、時間を食っているのはハフマンデコードの処理でした。(スライド辞書は遅くなりようもないので当然です。)
さすがに1ビットごとに二分探索するのは遅かったようで、別のアルゴリズムを模索中です。
ちょっと気になるのは、例外処理アンワインド情報の登録/解除だけで、3〜4秒もかかっていることです。
VC++だと状況は多少違ってくるかもしれませんが、UNLHA32.DLLに勝つのは厳しそうです。
以下、テストに使ったコードです。
ファイルのプロパティにアクセスする方法が変わっていますが、内容は無圧縮版の時とほぼ同じです。
#include <hamigaki/iostreams/device/lzh_file.hpp> #include <boost/filesystem/convenience.hpp> #include <boost/filesystem/operations.hpp> #include <boost/iostreams/device/file.hpp> #include <boost/iostreams/copy.hpp> #include <clocale> #include <exception> #include <iostream> namespace io_ex = hamigaki::iostreams; namespace fs = boost::filesystem; namespace io = boost::iostreams; int main(int argc, char* argv[]) { try { if (argc != 2) return 1; // これがないとfopen()でVC8で日本語ファイル名が化ける std::setlocale(LC_ALL, ""); fs::path::default_name_check(fs::no_check); typedef io_ex::lzh_file_source<io::file_source> lzh_type; lzh_type lzh(io::file_source(argv[1], std::ios_base::binary)); do { const io_ex::lha::basic_header& head = lzh.header(); if (head.attributes & io_ex::lha::attributes::directory) fs::create_directories(head.path); else { fs::create_directories(head.path.branch_path()); io::copy( lzh, io::file_sink( head.path.native_file_string(), std::ios_base::binary) ); } } while (lzh.next_entry()); return 0; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } return 1; }