【问题标题】:Ruby Zlib compression gives different outputs for the same inputRuby Zlib 压缩为相同的输入提供不同的输出
【发布时间】:2019-11-26 11:43:42
【问题描述】:

我有这种压缩字符串的 ruby​​ 方法 -

    def compress_data(data)
        output = StringIO.new
        gz = Zlib::GzipWriter.new(output)
        gz.write(data)
        gz.close

        compressed_data = output.string
        compressed_data
    end

当我用相同的输入调用这个方法时,我在不同的时间得到不同的输出。我正在尝试获取压缩输出的字节数组并进行比较。 当我运行以下命令时,输出为Different -

input = "hello world"

output1 = (compress_data input).bytes.to_a
sleep 1
output2 = (compress_data input).bytes.to_a
if output1 == output2
    puts 'Same'
else
    puts 'Different'
end

当我移除睡眠时,输出为Same。压缩算法和当前时间有关系吗?

【问题讨论】:

    标签: ruby compression gzip zlib


    【解决方案1】:

    选项 1 - 固定时间:

    是的。压缩时间存储在标头中。您可以使用mtime 方法将时间设置为固定值,这将解决您的问题:

    gz = Zlib::GzipWriter.new(output)
    gz.mtime = 1
    gz.write(data)
    gz.close
    

    注意the Ruby documentation 表示将mtime 设置为零将禁用时间戳。我试过了,它不起作用。我还查看了源代码,似乎缺少此功能。似乎是一个错误。因此,您必须将其设置为 0 以外的值(但请参阅下面的 cmets - 它将在未来的版本中修复)。

    选项 2 - 跳过标题:

    另一种选择是在检查类似数据时跳过标题。标头长 10 个字节,所以只检查数据:

    data = compress_data(input).bytes[10..-1]
    

    请注意,您无需在bytes 上致电to_a。它已经是一个数组:

    String.bytes -> an_array

    返回 str 中的字节数组。这是 str.each_byte.to_a 的简写。

    【讨论】:

    • 我检查了当前版本,但它尚未包含在内。所以它很可能会出现在 Ruby 2.6.6 或 2.7.0 中。
    • 他们还可以发布zlib gem 的新版本。有人只需要提出要求,因为我不相信他们有时间表或计划(比如 Ruby 版本)。
    • 谢谢!当我发现这个问题时,我实际上正在为压缩方法编写一个测试用例。在比较时忽略标头字节可以解决我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    相关资源
    最近更新 更多