データベースのブロブ フィールドに挿入する前に、Ruby で非常に大きな文字列 (テキスト フィールド) を圧縮する方法を検討しています。圧縮自体は簡単です。Zlib を使用するだけです。
ただし、同様の文字列のコピーがある可能性があるインスタンスも調べています。例えば。データベースにすでに何かが保存されている可能性があります-stringA. 変更により、stringB が得られます。stringA と stringB の差分の圧縮バージョンを保存して、stringA と圧縮された差分があれば、stringB を取得できるようにしたいと考えています。
これに適したライブラリはありますか?
理想的には、単一ステップのバイナリ差分圧縮です。人間が読めるテキストの差分は本当に必要ありません (より多くのスペースを浪費する可能性があります)。機械可読である必要があるだけです。diff -u oldFile newFile > mods.diff
したがって、 andを使用して圧縮することを提案しないでくださいpatch < mods.diff
。
答え
編集:回答の一部についてMark Adlerに感謝します(方法があることを知りませんでしたset_dictionary
)。これを Ruby で実行したいので、関連するメソッド名はset_dictionary
. ただし、これを実行しようとすることは、辞書がない場合よりもはるかに困難です。
辞書を使用せずに、次のことができます。
A = "My super string to be compressed. Compress me now to " \
"save the space used to store this super string."
cA = Zlib::Deflate.deflate(A)
# => "x\234U\214\301\r\200 \020\004[\331\nh\302\267E n\224\a\034\271;4v..."
Zlib::Inflate.inflate(cA)
# => "My super string to be compressed. Compress me now to save the..."
Zlib::FINISH
ただし、辞書を使用するには、 deflate に渡して出力をフラッシュし、インフレートZlib::NeedDict
時に辞書を追加する前に例外を許可する必要があります。
B = "A super string with differences, let's see how much " \
"extra space the differences will take in this super string!"
zlib_deflate = Zlib::Deflate.new
zlib_deflate .set_dictionary(A)
dB = zlib_deflate .deflate(B, Zlib::FINISH)
# => "x\2733\324$\230sD\265\242<\263$C!%3--\265(5/9\265XG!'\265D\035\250..."
zlib_inflate = Zlib::Inflate.new
zlib_inflate.inflate(dB) # Exception thrown
# => Exception: Zlib::NeedDict: need dictionary
zlib_inflate.set_dictionary(A)
zlib_inflate.inflate(dB)
# => "A super string with differences, let's see how much extra space the..."