【发布时间】:2012-09-02 22:09:32
【问题描述】:
我正在研究在将 Ruby 中的一些非常大的字符串(文本字段)插入数据库 blob 字段之前对其进行压缩。压缩本身很简单,我可以用Zlib。
但是,我也在研究可能有类似字符串副本的情况。例如。我可能已经在数据库中存储了一些东西 - stringA。修改给了我stringB。我想存储 stringA 和 stringB 之间差异的压缩版本,这样如果我有 stringA 和压缩后的差异,我可以取回 stringB。
有合适的库吗?
理想情况下,这将是单步二进制差异压缩。我真的不想要人类可读的文本差异(这可能会浪费更多空间)。它只需要机器可读。因此请不要建议我使用diff -u oldFile newFile > mods.diff 和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 以放气以刷新输出,并在充气时添加字典之前允许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..."
【问题讨论】:
标签: ruby string compression diff