为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用与.Net兼容的GZIPOutputStream压缩和解压缩字符串?

如何使用与.Net兼容的GZIPOutputStream压缩和解压缩字符串?

素胚勾勒不出你 2019-09-02 08:13:04
我需要一个在android中使用GZip压缩字符串的示例。我想向方法发送一个像“hello”这样的字符串并获得以下压缩字符串:BQAAAB + LCAAAAAAABADtvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee ++ 997o7nU4n99 // P1xmZAFs9s5K2smeIYCqyB8 / fnwfPyLmeVlW / W + GphA2BQAAAA ==然后我需要解压缩它。谁能给我一个例子并完成以下方法?private String compressString(String input) {    //...}private String decompressString(String input) {    //...}谢谢,更新根据scessor的回答,现在我有以下4种方法。Android和.net压缩和解压缩方法。除一种情况外,这些方法彼此兼容。我的意思是它们在前3个状态中兼容但在第4个状态下不兼容:状态1)Android.compress < - > Android.decompress :( 好的)状态2)Net.compress < - > Net.decompress :( 好的)状态3)Net.compress - > Android.decompress :( 好的)状态4)Android.compress - > .Net.decompress :( 不行)任何人都可以解决它吗?Android方法:public static String compress(String str) throws IOException {    byte[] blockcopy = ByteBuffer            .allocate(4)            .order(java.nio.ByteOrder.LITTLE_ENDIAN)            .putInt(str.length())            .array();    ByteArrayOutputStream os = new ByteArrayOutputStream(str.length());    GZIPOutputStream gos = new GZIPOutputStream(os);    gos.write(str.getBytes());    gos.close();    os.close();    byte[] compressed = new byte[4 + os.toByteArray().length];    System.arraycopy(blockcopy, 0, compressed, 0, 4);    System.arraycopy(os.toByteArray(), 0, compressed, 4,            os.toByteArray().length);    return Base64.encode(compressed);}public static String decompress(String zipText) throws IOException {    byte[] compressed = Base64.decode(zipText);    if (compressed.length > 4)    {        GZIPInputStream gzipInputStream = new GZIPInputStream(                new ByteArrayInputStream(compressed, 4,                        compressed.length - 4));        ByteArrayOutputStream baos = new ByteArrayOutputStream();        for (int value = 0; value != -1;) {            value = gzipInputStream.read();            if (value != -1) {                baos.write(value);            }        
查看完整描述

3 回答

?
茅侃侃

TA贡献1842条经验 获得超21个赞

无论是什么压缩“BQAAAB + LC”的“Hello”都是gzipper特别差的实现。它扩展了“Hello”远远超过必要的范围,使用动态块而不是deflate格式的静态块。删除gzip流的四字节前缀(始终以hex 1f 8b开头)后,“Hello”扩展为123字节。在压缩世界中,这被视为犯罪。


您抱怨的Compress方法正常且正常。它生成一个静态块,总输出为25个字节。gzip格式具有10字节头和8字节尾部开销,使得5字节输入已经被编码为7个字节。这还差不多。


不可压缩的流将被扩展,但它不应该太多。对于不可压缩数据,gzip使用的deflate格式将为每16K到64K增加5个字节。


为了获得实际的压缩,通常你需要为压缩器提供更多的工作来处理这五个字节,这样它就可以在可压缩数据中找到重复的字符串和有偏差的统计数据。我知道你只是用短字符串进行测试。但是在实际应用中,你永远不会使用具有这种短字符串的通用压缩器,因为发送字符串总是更好。


查看完整回答
反对 回复 2019-09-02
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

我在我的项目中尝试了你的代码,并在Android上的compress方法中发现了一个编码错误:


byte[] blockcopy = ByteBuffer

        .allocate(4)

        .order(java.nio.ByteOrder.LITTLE_ENDIAN)

        .putInt(str.length())

        .array();

ByteArrayOutputStream os = new ByteArrayOutputStream(str.length());

GZIPOutputStream gos = new GZIPOutputStream(os);

gos.write(str.getBytes());

在上面的代码中,你应该使用更正的编码,并填充字节长度,而不是字符串长度:


byte[] data = str.getBytes("UTF-8");


byte[] blockcopy = ByteBuffer

        .allocate(4)

        .order(java.nio.ByteOrder.LITTLE_ENDIAN)

        .putInt(data.length)

            .array();


ByteArrayOutputStream os = new ByteArrayOutputStream( data.length );    

GZIPOutputStream gos = new GZIPOutputStream(os);

gos.write( data );


查看完整回答
反对 回复 2019-09-02
  • 3 回答
  • 0 关注
  • 534 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信