Skip to content

dearblue/ruby-extlz4

Repository files navigation

extlz4 - LZ4 for ruby

圧縮伸張ライブラリ lz4 (https://github.com/lz4/lz4/) の非公式 ruby バインディングライブラリです。

LZ4 データストリームを圧縮・伸張できます。lz4-cli で扱うことが出来ます。

$ dmesg | ruby -r extlz4 -e 'LZ4.encode_file($stdin.binmode, $stdout.binmode)' | lz4c -d | more

ほかの ruby 向けの lz4 バインディングライブラリとしては KOMIYA Atsushi さんによる lz4-ruby (http://rubygems.org/gems/lz4-ruby) があります。

FEATURES (機能)

  • Generic LZ4 frame data process (for .lz4 file format)
    • Decode LZ4 Frame data : LZ4.decode
    • Encode LZ4 Frame data : LZ4.encode
  • Generic LZ4 frame data file process (for .lz4 file format)
    • Decode LZ4 Frame data file : LZ4.decode_file
    • Encode LZ4 Frame data file : LZ4.encode_file
  • LZ4 block data process
    • Decode LZ4 block data : LZ4.block_decode
    • Encode LZ4 block data : LZ4.block_encode (supporting high compression level)
    • Streaming Decode LZ4 block data : LZ4.block_stream_decode and LZ4::BlockDecoder#update
    • Streaming Encode LZ4 block data : LZ4.block_stream_encode and LZ4::BlockEncoder#update (supporting high compression level)

See Quick reference for more details.

ATTENTIONS (注意事項)

  • Many documents are written in japanese.

    (ドキュメントの多くは日本語で記述されています)

extlz4-0.1 による不正な lz4 ストリームを出力する不具合について

extlz4-0.1 に不正な lz4 ストリームを出力する不具合がありました。

詳しく説明すると、ブロックデータとともに格納時ブロックデータサイズも出力しますが、常に圧縮後のデータサイズを出力していました。圧縮していない (圧縮後のデータサイズが圧縮前のデータサイズを上回った) 場合であれば、圧縮前のデータサイズを出力するべきところですが、そうはなっていません。

これによって無圧縮ブロックデータが正しく読み込めず、ひいてはそのブロック以降のデータが正しく読み込めないということになります。

extlz4-0.1.1 でその不具合の修正を行いました。

また、不正な lz4 ストリームファイルを生成しなおかつオリジナルファイルも失われた場合は、同梱してある bin/extlz4 プログラムに --fix-extlz4-0.1-bug を指定することで正しい lz4 ストリームファイルを出力できます。

extlz4 --fix-extlz4-0.1-bug <file>...

出力ファイル名は、入力ファイル名の頭に "fixed-" を追加したものとなります。

必要であれば -f スイッチが利用できます。

-k スイッチは無視されます。修復した lz4 ストリームファイルが正しいかを検査したあとで不正な lz4 ストリームファイルと差し替えて下さい。

修復できるのはあくまで extlz4-0.1 のこの不具合に起因するファイルのみとなります。

EXAMPLES (用例)

First, load extlz4. (最初に extlz4 を読み込んでください)

require "extlz4"

One shot decoding from LZ4 Frame (LZ4 Frame 伸張処理)

uncompressed_data_string = LZ4.decode(compressed_data_string)

One shot encoding to LZ4 Frame (LZ4 Frame 通常圧縮処理)

compressed_data_string = LZ4.encode(uncompressed_data_string)

One shot high compression encoding to LZ4 Frame (LZ4 Frame 高圧縮処理)

compressed_data_string = LZ4.encode(uncompressed_data_string, 9)

Stream decoding to LZ4 Frame

File.open("sample.txt.lz4", "rb") do |file|
  LZ4.decode(file) do |lz4|
    lz4.read(50)  # read 50 bytes as string
    lz4.getc      # read 1 byte as integer
    lz4.read      # read rest bytes as string
  end
end

Stream encoding by high compression to LZ4 Frame

File.open("sample.txt.lz4", "wb") do |file|
  LZ4.encode(file, 9) do |lz4|
    lz4 << "#{Time.now}: abcdefghijklmnopqrstuvwxyz\n"
    lz4.write "#{Time.now}: abcdefghijklmnopqrstuvwxyz\n"
  end
end

Stream encoding without block to LZ4 Frame

file = File.open("sample.txt.lz4", "wb")
lz4 = LZ4.encode(file)
lz4 << "abcdefghijklmnopqrstuvwxyz\n"
lz4.close  # VERY IMPORTANT!

One shot block data processing to/from LZ4 Block (fast compression encoding and decoding)

src = "abcdefg" * 100
lz4data = LZ4.block_encode(src)
data = LZ4.block_decode(lz4data)
p src == data  # => true

One shot block data processing to/from LZ4 Block (high compression encoding and decoding)

src = "abcdefg" * 100
level = 8
lz4data = LZ4.block_encode(level, src)
data = LZ4.block_decode(lz4data)
p src == data  # => true

One shot block data processing to/from LZ4 Block (high speed encoding)

src = "abcdefg" * 100
level = -19 # transform to one's complement as acceleration
lz4data = LZ4.block_encode(level, src)

Block stream data processing to/from LZ4 Block (high compression encoding and decoding)

level = 8 # (OPTIONAL PARAMETER)
predict = "abcdefg" # with preset dictionary (OPTIONAL PARAMETER)
encoder = LZ4.block_stream_encode(level, predict)

src = "abcdefg" * 100
lz4data1 = encoder.update(src)

decoder = LZ4.block_stream_decode(predict)

data = decoder.update(lz4data1)
p src == data  # => true

src2 = "ABCDEFG" * 100
lz4data2 = encoder.update(src2)
p "lz4data1.bytesize" => lz4data1.bytesize,
  "lz4data2.bytesize" => lz4data2.bytesize

data = decoder.update(lz4data2)
p src2 == data  # => true

Support Ractor with Ruby3

Ruby3 で追加された Ractor に対応しています。

BONUS (おまけ)

コマンドラインプログラムとして extlz4 が追加されます。

これは lz4 と同程度の機能を持ちます (車輪の再発明とも言う)。

とはいえ、引数のとり方を変えてあり、gzip のような形で利用できます。

SPECIFICATION (仕様)

About

ruby bindings for lz4

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published