我如何编写一个方法来压缩不包含头文件的Gzip字符串,并将其压缩到与解压缩之前完全相同的方式。原始压缩是在C#中完成的,我使用以下方法在Ruby中进行膨胀:
编辑:基本上,我希望匹配的deflate方法来实现这种膨胀:
def inflate(string)
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
buf = zstream.inflate(string)
zstream.finish
zstream.close
buf
end
在解压缩之前,字符串是:
"5\x891\n\xC30\x10\x04{\xBDb\xEB\xE0F&\x81\xA4\xCA3\xDC\xA81\xD2\x1A]\xA1\x13\xB1.\x100\xFEF\xDE\e\x19\x9Cb\x99Yf\xCA\xB3A\x1A,\x13\xB1\x96R\x15I\x96\x85+5\x12\xA2=\xF4:\xAFb\xB9\xD0$\xA2\xF1\xF5>\xDA\xD3\xB9\x9A\xA8f\xFC\xD8\xE6\xFD\x00\x7F\xEB{\f!Uk{\xCF,\x91\xDC\x1C\x10J\xC4\xF7z\xCA\xE8p9\xF8\xFF\xF7\x93\xDEw\xD9\x7F"
使用inflate解压后,它是:
"What is the common difference in this arithmetic sequence?\n\n\\indenttext{11, 15, 19,\\dots}\n\n\\emcee{\n \\mc \x964\n \\mc 2\n *\\mc 4\n \\mc 8\n \\mc 11\n }"
我尝试过创建多个deflate方法,但没有一个能让它恢复原状。谢谢你的帮助!
编辑:原始压缩是在.NET 2.0中使用以下
完成的byte[] compressedStringBytes = CompressGzipString(String);
和CompressGzipString确实:
MemoryStream compressed = new MemoryStream();
DeflaterOutputStream zosCompressed = new DeflaterOutputStream(compressed, new Deflater(Deflater.BEST_COMPRESSION, true));
zosCompressed.Write(data, 0, data.Length);
如果不可能将它变为完全原始的,那么最标准化的压缩是什么,我的意思是一般的,并且能够以与原始相同的方式解压缩?
答案 0 :(得分:2)
这取决于它在C#中的压缩程度;在.NET 4.5之前,C#中的System.IO.DeflateStream/GZipStream
类使用了与zlib显着不同的DEFLATE的Microsoft实现(这意味着您可能无法使用zlib轻松地模拟它)。在几乎所有情况下都要糟糕得多,所以在.NET 4.5中,他们用zlib替换它,应该能够匹配你在Ruby中可以做的事情。
如果您知道C#的哪个版本生成了该字符串,您可以确定是否可以返回原始字节。如果它是使用.NET 4.5生成的,那么你应该能够使用相同的设置进行标准的deflate来获得相同的字节。
答案 1 :(得分:0)
不同的压缩器,相同压缩器的不同版本或相同压缩器的不同设置的相同版本,即使它们都使用相同的压缩数据格式(例如放气),也可以并且经常会为同一输入产生不同的输出)。唯一可以肯定的是,当你解压缩时,你会得到完全相同的东西。事实上,这确实是你需要保证的。为什么要完全相同的压缩流?
正如Ron Warholic所指出的那样,你甚至不希望在.NET 4.5之前从.NET破坏的deflate实现中恢复到相同的压缩输出。由于.NET 2.0使用了自己独特的,破坏的,deflate实现,因此您无法使用使用zlib的ruby复制它。
同样如Ron Warholic所述,ruby和.NET 4.5或更高版本都使用zlib,因此两者都应生成相同的压缩输出,并选择相同的压缩级别。虽然这不能永远保证,因为新版本的zlib可能产生不同的输出,而ruby或.NET中的一个可能会更新,而另一个则不会。同样如下所述,您无法使用.NET的类直接控制压缩级别。
如果不可能将它变为原始的,那将是什么 最标准化的压缩,我指的是一般的压缩 能够以与原始相同的方式解压缩 是
无损压缩和解压缩的任何正确实现都将具有此属性。无论压缩数据如何不同,您都将始终返回到原始的原始数据。没有“最标准化的压缩”。
您的Zlib::Inflate.new(-Zlib::MAX_WBITS)
期待一个原始的deflate流,没有标题或预告片。所以你需要在C#端生成它。
从.NET documentation不清楚DeflateStream
类是否压缩为deflate格式或zlib格式(后者是带有zlib包装器的deflate格式,由两个前缀字节组成,用于数据完整性检查的四个后缀字节)。如果它压缩为deflate格式,那么它将与您的Zlib::Inflate.new(-Zlib::MAX_WBITS)
兼容。如果它压缩为zlib格式,那么它将与Zlib::Inflate.new(Zlib::MAX_WBITS)
兼容(即没有减号)。或者您可以删除前两个字节和后四个字节以返回到deflate流。
.NET中的DeflateStream
类有点奇怪,因为CompressionLevel
只有enum
只有三个选项,而不是zlib提供的十个级别(0..9) )。这三个选项包括Optimal
,Fastest
和NoCompression
。最后一个必须是0,第一个可能是9,中间一个可能是1或3.在任何情况下,没有默认压缩级别的选项!该级别(6)是压缩与时间的非常好的平衡。
您可能需要考虑使用DotNetZip。它为zlib提供了一个完整的界面,因此您可以准确指定您想要做的事情,并知道会发生什么。