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

59

我需要一个在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: (OK)
  • 第2种状态) Net.compress <-> Net.decompress: (OK)
  • 第3种状态) Net.compress -> Android.decompress: (OK)
  • 第4种状态) Android.compress -> .Net.decompress: (NOT OK)

有人能解决这个问题吗?

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);
            }
        }
        gzipInputStream.close();
        baos.close();
        String sReturn = new String(baos.toByteArray(), "UTF-8");
        return sReturn;
    }
    else
    {
        return "";
    }
}

.Net方法:

public static string compress(string text)
{
    byte[] buffer = Encoding.UTF8.GetBytes(text);
    MemoryStream ms = new MemoryStream();
    using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
    {
        zip.Write(buffer, 0, buffer.Length);
    }

    ms.Position = 0;
    MemoryStream outStream = new MemoryStream();

    byte[] compressed = new byte[ms.Length];
    ms.Read(compressed, 0, compressed.Length);

    byte[] gzBuffer = new byte[compressed.Length + 4];
    System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
    System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
    return Convert.ToBase64String(gzBuffer);
}

public static string decompress(string compressedText)
{
    byte[] gzBuffer = Convert.FromBase64String(compressedText);
    using (MemoryStream ms = new MemoryStream())
    {
        int msgLength = BitConverter.ToInt32(gzBuffer, 0);
        ms.Write(gzBuffer, 4, gzBuffer.Length - 4);

        byte[] buffer = new byte[msgLength];

        ms.Position = 0;
        using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
        {
            zip.Read(buffer, 0, buffer.Length);
        }

        return Encoding.UTF8.GetString(buffer);
    }
}

compressString的结果不能是String,必须是bytes[]。同样地,decompressString的输入不能是String,也必须是bytes[] - JBM
vice versa”是什么意思?使用String压缩GZIPOutputStream?;-) - user207421
我的 .Net 方法创建了一个大字符串,与 Android 中压缩方法的结果不同。我更新了我的问题并插入了 .Net 压缩和解压缩方法。有人能否更改这些方法以创建相同的压缩字符串? - Bobs
有许多可能的有效的“压缩”字符串可以解压成字符串“Hello”。如果两个不同的压缩器产生不同的输出,那没关系,只要它们在所有输出上正确解压即可。你从不正确的情况下获得了什么解压缩器的输出? - Stobor
@breceivemail - 你的问题很可能与.NET版本有关。请查看我更新的C#和Java类的版本,应该可以100%正常工作,并且包含Base64编码,以便那些需要使用JSON进行传输的人使用:https://dev59.com/oGw15IYBdhLWcg3wSJo3#36126217 - nikib3ro
显示剩余2条评论
10个回答

95

GZIP方法:

public static byte[] compress(String string) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
    GZIPOutputStream gos = new GZIPOutputStream(os);
    gos.write(string.getBytes());
    gos.close();
    byte[] compressed = os.toByteArray();
    os.close();
    return compressed;
}

public static String decompress(byte[] compressed) throws IOException {
    final int BUFFER_SIZE = 32;
    ByteArrayInputStream is = new ByteArrayInputStream(compressed);
    GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
    StringBuilder string = new StringBuilder();
    byte[] data = new byte[BUFFER_SIZE];
    int bytesRead;
    while ((bytesRead = gis.read(data)) != -1) {
        string.append(new String(data, 0, bytesRead));
    }
    gis.close();
    is.close();
    return string.toString();
}

还有一个测试:

final String text = "hello";
try {
    byte[] compressed = compress(text);
    for (byte character : compressed) {
        Log.d("test", String.valueOf(character));
    }
    String decompressed = decompress(compressed);
    Log.d("test", decompressed);
} catch (IOException e) {
    e.printStackTrace();
}

=== 更新 ===

如果您需要与 .Net 兼容,我的代码需要做一些更改:

public static byte[] compress(String string) throws IOException {
    byte[] blockcopy = ByteBuffer
        .allocate(4)
        .order(java.nio.ByteOrder.LITTLE_ENDIAN)
        .putInt(string.length())
        .array();
    ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
    GZIPOutputStream gos = new GZIPOutputStream(os);
    gos.write(string.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 compressed;
}

public static String decompress(byte[] compressed) throws IOException {
    final int BUFFER_SIZE = 32;
    ByteArrayInputStream is = new ByteArrayInputStream(compressed, 4, compressed.length - 4);
    GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
    StringBuilder string = new StringBuilder();
    byte[] data = new byte[BUFFER_SIZE];
    int bytesRead;
    while ((bytesRead = gis.read(data)) != -1) {
        string.append(new String(data, 0, bytesRead));
    }
    gis.close();
    is.close();
    return string.toString();
}

你可以使用相同的测试脚本。


3
佩服你!这个网站上很少有人知道单元测试以及其重要性。你赢得了应得的赞! - JBM
感谢您的答复。我测试了您的解决方案,但是没有得到字符串:“BQAAAB + LCAAAAAAABADtvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee ++ 997o7nU4n99 // P1xmZAFs9s5K2smeIYCqyB8 / fnwfPyLmeVlW / w + GphA2BQAAAA ==”您的方法的结果与它不同。所提到的字符串是由.Net中的gzip算法生成的单词“hello”。我需要生成此字符串。我该怎么做? - Bobs
这个方法在DELPHI中是否可用?我需要一个在Java中压缩并在Delphi中解压缩的解决方案。有可能吗? - rolling.stones
在 compress() 中,您似乎将 ByteArrayOutputStream 初始化为错误的大小。不能安全地假设 string.length() == string.getBytes().length。 - Nir Pear
我在压缩时遇到了困难,直到我添加了gis.finish(); - scottyab
显示剩余11条评论

15
无论怎样把"Hello"压缩成BQAAAB+LC...的方式都是一种非常糟糕的gzip实现。它使用了动态块而不是在deflate格式中使用静态块,将"Hello"扩展得比必要的更多。删除gzip流的四字节前缀后(该前缀始终以十六进制1f 8b开头),"Hello"被扩展为123个字节。在压缩领域,这被认为是一种罪行。
你所抱怨的Compress方法正在正确地工作和使用。它生成一个静态块和总输出25个字节。gzip格式具有十字节的标题和八字节的尾部开销,使五字节的输入已编码为七字节。这更像它应该的样子。
无法压缩的流会被扩展,但不应过多。 gzip使用的deflate格式对于不可压缩数据每16K到64K增加五个字节。
要实现实际的压缩,通常需要提供比五个字节更多的内容,以便压缩器可以在可压缩数据中找到重复的字符串和有偏差的统计数据。我了解您只是在测试一个短字符串。但在实际应用中,您永远不会使用通用压缩器来处理如此短的字符串,因为直接发送该字符串总是更好的。

4
在您的Decompress()方法中,在传递给GZipInputStream之前跳过了Base64解码输入的前4个字节。在这种特定情况下,这些字节被发现为05 00 00 00。所以在Compress()方法中,在进行Base64编码之前,这些字节必须被放回去。
如果我这样做,Compress()返回以下内容:
BQAAAB+LCAAAAAAAAADLSM3JyQcAhqYQNgUAAAA=

我知道这不完全符合你的期望,而你希望的是:

BQAAAB+LCAAAAAAABADtvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee++997o7nU4n99//P1xmZAFs9s5K2smeIYCqyB8/fnwfPyLmeVlW/w+GphA2BQAAAA==

但是,如果我的结果再次输入Decompress(),我认为你仍然会得到"Hello"。试试看。差异可能是由于您获得原始字符串时使用的不同压缩级别。

那么神秘的前缀字节05 00 00 00是什么?根据这个答案,它可能是压缩字符串的长度,以便程序知道解压后的字节缓冲区应该有多长。但在这种情况下并不符合。

这是用于压缩()的修改后代码:

public static String Compress(String text) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    // TODO: Should be computed instead of being hard-coded
    baos.write(new byte[]{0x05, 0, 0, 0}, 0, 4);

    GZIPOutputStream gzos = new GZIPOutputStream(baos);
    gzos.write(text.getBytes());
    gzos.close();

    return Base64.encode(baos.toByteArray());
}

更新:

Android和.NET代码中输出字符串不匹配的原因是,.NET GZip实现进行了更快的压缩(因此输出更大)。可以通过查看原始Base64解码字节值来验证这一点:

.NET:

1F8B 0800 0000 0000 0400 EDBD 0760 1C49
9625 262F 6DCA 7B7F 4AF5 4AD7 E074 A108
8060 1324 D890 4010 ECC1 88CD E692 EC1D
6947 2329 AB2A 81CA 6556 655D 6616 40CC
ED9D BCF7 DE7B EFBD F7DE 7BEF BDF7 BA3B
9D4E 27F7 DFFF 3F5C 6664 016C F6CE 4ADA
C99E 2180 AAC8 1F3F 7E7C 1F3F 22E6 7959
56FF 0F86 A610 3605 0000 00

我的Android版本:

1F8B 0800 0000 0000 0000 CB48 CDC9 C907
0086 A610 3605 0000 00

现在,如果我们检查GZip文件格式,我们会发现.NET和Android版本在初始头部和尾部CRC32和大小字段上大多相同。唯一的区别在于以下字段:

  • XFL = 04(压缩器使用最快的算法)在.NET的情况下,而在Android中为00
  • 实际压缩块

因此从XFL字段清楚地表明了.NET压缩算法产生了更长的输出。

事实上,当我使用这些原始数据值创建一个二进制文件,然后使用gunzip解压缩它们时,.NET和Android版本都给出了与“hello”完全相同的输出

所以你不必担心不同的结果。


1
生成更多输出并不会更快,反而会更慢。在静态和动态决策之前查找匹配字符串需要相同的时间。对于静态和动态预测输出大小并做出正确决策(静态)几乎不需要时间。然后,在这种情况下,为静态生成更短的输出需要更少的时间。这里的权衡不是更快的压缩器,而是更短的开发时间(或懒惰的开发人员),不编写完整的解压程序。 - Mark Adler
@MarkAdler 你也许是对的,但我所要表达的是这两种方法给出不同结果是因为它们的压缩方案不同。楼主关心的是为什么结果会有差异。 - Dheeraj Vepakomma

4

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

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 );

3

好的,尽管已经有很多回答了,但是不幸的是,大部分都因为各种原因是错误的:

  • 在.NET Framework中,GZIP算法之间存在差异。如果您使用的是.NET 4.5,则大多数不同答案中出现的抱怨对您并不适用(而适用于使用2.0或3.5的人)。如果您选择“修复”版本的代码,实际上会搞乱压缩/解压缩。
  • Java使用无符号byte[],.NET使用有符号byte[]。这可能会在传输期间引起问题,具体取决于您如何传输该byte[]。
  • 我曾经使用Base64来传输byte[],这可能会带来更多问题。还有其他各种原因,但让我们跳过进一步的抱怨并进入代码...

如果您使用.NET Framework 4.5,则需要以下C#类(其中包含Base64作为奖励):

public class CompressString
{
    private static void CopyTo(Stream src, Stream dest)
    {
        byte[] bytes = new byte[4096];
        int cnt;

        while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0)
        {
            dest.Write(bytes, 0, cnt);
        }
    }

    public static byte[] Zip(string str)
    {
        var bytes = Encoding.UTF8.GetBytes(str);

        using (var msi = new MemoryStream(bytes))
        using (var mso = new MemoryStream())
        {
            using (var gs = new GZipStream(mso, CompressionMode.Compress))
            {
                //msi.CopyTo(gs);
                CopyTo(msi, gs);
            }

            return mso.ToArray();
        }
    }

    public static string Unzip(byte[] bytes)
    {
        using (var msi = new MemoryStream(bytes))
        using (var mso = new MemoryStream())
        {
            using (var gs = new GZipStream(msi, CompressionMode.Decompress))
            {
                //gs.CopyTo(mso);
                CopyTo(gs, mso);
            }

            return Encoding.UTF8.GetString(mso.ToArray());
        }
    }

    // Base64
    public static string ZipBase64(string compress)
    {
        var bytes = Zip(compress);
        var encoded = Convert.ToBase64String(bytes, Base64FormattingOptions.None);
        return encoded;
    }

    public static string UnzipBase64(string compressRequest)
    {
        var bytes = Convert.FromBase64String(compressRequest);
        var unziped = Unzip(bytes);
        return unziped;
    }

    // Testing
    public static bool TestZip(String stringToTest)
    {
        byte[] compressed = Zip(stringToTest);
        Debug.WriteLine("Compressed to " + compressed.Length + " bytes");
        String decompressed = Unzip(compressed);
        Debug.WriteLine("Decompressed to: " + decompressed);

        return stringToTest == decompressed;
    }
}

这里提供 Android/Java 类:

public class CompressString {
    public static byte[] compress(String string) {
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
            GZIPOutputStream gos = new GZIPOutputStream(os);
            gos.write(string.getBytes());
            gos.close();
            byte[] compressed = os.toByteArray();
            os.close();
            return compressed;
        } catch (IOException ex) {
            return null;
        }
    }

    public static String decompress(byte[] compressed) {
        try {
            final int BUFFER_SIZE = 32;
            ByteArrayInputStream is = new ByteArrayInputStream(compressed);
            GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
            byte[] data = new byte[BUFFER_SIZE];
            int bytesRead;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((bytesRead = gis.read(data)) != -1) {
                baos.write(data, 0, bytesRead);
            }
            gis.close();
            is.close();
            return baos.toString("UTF-8");
        } catch (IOException ex) {
            return null;
        }
    }    

    // Base64
    public static String compressBase64(String strToCompress) {
        byte[] compressed = compress(strToCompress);
        String encoded = android.util.Base64.encodeToString(compressed, android.util.Base64.NO_WRAP);
        return encoded;
    }

    public static String decompressBase64(String strEncoded) {
        byte[] decoded = android.util.Base64.decode(strEncoded, android.util.Base64.NO_WRAP);
        String decompressed = decompress(decoded);
        return decompressed;
    }


    // test
    public static boolean testCompression(String stringToTest) {
        byte[] compressed = compress(stringToTest);
        Log.d("compress-test", "Compressed to " + compressed.length + " bytes");
        String decompressed = decompress(compressed);
        Log.d("compress-test", "Decompressed to " + decompressed);

        return stringToTest.equals(decompressed);
    }
}

所以,这里有一些不依赖任何库的、百分之百可用的压缩Android/Java/C#/.NET类。如果你发现某个字符串在.NET 4.5上无法使用(我已经尝试了从“Hello world”到1000字短篇小说的所有内容),请告诉我。


看起来很有前途,但我尝试了使用C# API压缩的20k JSON文件,Android说它是坏的base64。 - Micah Montoya
@ClumsyHamster 请上传您的文件并在此处留下链接... 我已经在多个项目中使用了这段代码,它对我来说百分之百有效。 - nikib3ro
没事了,我刚刚想通了我做错了什么。我返回了一个对象的对象,只有对象被压缩了,但我尝试压缩对象本身,而它还没有被压缩。很抱歉浪费了你的时间。 - Micah Montoya

2

我对这个问题感到非常困惑。最后,在我的情况下(.Net 4),为了实现.Net兼容性,不需要在开头添加这额外的4个字节。

它的工作原理很简单:

Android压缩:

public static byte[] compress(String string) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
    GZIPOutputStream gos = new GZIPOutputStream(os);
    gos.write(string.getBytes());
    gos.close();
    byte[] compressed = os.toByteArray();
    os.close();
    return compressed;
}

.Net 解压缩

public static byte[] DecompressViD(byte[] gzip)
    {
        // Create a GZIP stream with decompression mode.
        // ... Then create a buffer and write into while reading from the GZIP stream.
        using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
        {
            const int size = 4096;
            byte[] buffer = new byte[size];
            using (MemoryStream memory = new MemoryStream())
            {
                int count = 0;
                do
                {
                    count = stream.Read(buffer, 0, size);
                    if (count > 0)
                    {
                        memory.Write(buffer, 0, count);
                    }
                }
                while (count > 0);
                return memory.ToArray();
            }
        }
    }

0

这里有一个简单的例子,让你开始。

public static void main(String[] args) throws IOException 
{
    byte[] buffer = new byte[4096];
    StringBuilder sb = new StringBuilder();

    //read file to compress

    String read = readFile( "spanish.xml", Charset.defaultCharset());

    if( read != null )
    {
        //compress file to output

        FileOutputStream fos = new FileOutputStream("spanish-new.xml");
        GZIPOutputStream gzos = new GZIPOutputStream(fos);
        gzos.write( read.getBytes());
        gzos.close();

        //uncompress and read back

        FileInputStream fis = new FileInputStream("spanish-new.xml");
        GZIPInputStream gzis = new GZIPInputStream(fis);

        int bytes = 0;

        while ((bytes = gzis.read(buffer)) != -1) {
            sb.append( new String( buffer ) );
        }
    }
}

static String readFile(String path, Charset encoding) throws IOException {
    byte[] encoded = Files.readAllBytes(Paths.get(path));
    return new String(encoded, encoding);
}

0

Android方法解压缩不正常

Android压缩 -> 正常:

public static byte[] compress(String string) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
    GZIPOutputStream gos = new GZIPOutputStream(os);
    gos.write(string.getBytes());
    gos.close();
    byte[] compressed = os.toByteArray();
    os.close();
    return compressed;
}

.Net解压缩 -> 成功:

public static byte[] DecompressViD(byte[] gzip)
{
    // Create a GZIP stream with decompression mode.
    // ... Then create a buffer and write into while reading from the GZIP stream.
    using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
    {
        const int size = 4096;
        byte[] buffer = new byte[size];
        using (MemoryStream memory = new MemoryStream())
        {
            int count = 0;
            do
            {
                count = stream.Read(buffer, 0, size);
                if (count > 0)
                {
                    memory.Write(buffer, 0, count);
                }
            }
            while (count > 0);
            return memory.ToArray();
        }
    }
}

.Net 压缩 -> 成功:

    public static string compress(string text)
    {
        byte[] buffer = Encoding.UTF8.GetBytes(text);
        MemoryStream ms = new MemoryStream();
        using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
        {
            zip.Write(buffer, 0, buffer.Length);
        }

        ms.Position = 0;
        MemoryStream outStream = new MemoryStream();

        byte[] compressed = new byte[ms.Length];
        ms.Read(compressed, 0, compressed.Length);

        return Convert.ToBase64String(compressed);
    }

Android解压缩 -> 不OK:

public static String decompress(String zipText) throws IOException {
    byte[] compressed = Base64.decode(zipText);

    GZIPInputStream os = new GZIPInputStream(new ByteArrayInputStream(compressed));

    GZIPInputStream gzipInputStream = new GZIPInputStream(os);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    for (int value = 0; value != -1;) {
        value = gzipInputStream.read();
        if (value != -1) {
            baos.write(value);
        }
    }
    gzipInputStream.close();
    baos.close();

    return new String(baos.toByteArray(), "UTF-8");
}

0
这可能有点晚,但对某些人可能有用, 最近我在C# Xamarin中需要压缩一个字符串并在Android中解压缩它。基本上,Xamarin Android应用程序发送带有压缩的额外字符串的意图到另一个本地Android应用程序。而Android应用程序必须在使用之前解压缩它。
以下是对我有效的方法。
ANDROID解压缩
 public static String decompress(String zipText) throws IOException {
    int size = 0;
    byte[] gzipBuff = Base64.decode(zipText,Base64.DEFAULT);
    ByteArrayInputStream memstream = new ByteArrayInputStream(gzipBuff, 4,gzipBuff.length - 4);
    GZIPInputStream gzin = new GZIPInputStream(memstream);
    final int buffSize = 8192; 
   byte[] tempBuffer = new byte[buffSize];
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
  while ((size = gzin.read(tempBuffer, 0, buffSize)) != -1) { 
   baos.write(tempBuffer, 0, size);
  } byte[] buffer = baos.toByteArray();
  baos.close(); return new String(buffer, StandardCharsets.UTF_8);
  }

XAMARIN 压缩

public static string CompressString(string text)
    {
        byte[] buffer = Encoding.UTF8.GetBytes(text);
        var memoryStream = new MemoryStream();
        using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
        {
            gZipStream.Write(buffer, 0, buffer.Length);
        }
        memoryStream.Position = 0;
        var compressedData = new byte[memoryStream.Length];
        memoryStream.Read(compressedData, 0, compressedData.Length);
        var gZipBuffer = new byte[compressedData.Length + 4];
        Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length);
        Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4);
        return Convert.ToBase64String(gZipBuffer);
    }

-2

我在Vb.net中这样做:

  Public Function zipString(ByVal Text As String) As String
    Dim res As String = ""
    Try

        Dim buffer As Byte() = System.Text.Encoding.UTF8.GetBytes(Text)
        Dim ms As New MemoryStream()
        Using zipStream As New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Compress, True)
            zipStream.Write(buffer, 0, buffer.Length)
        End Using
        ms.Position = 0
        Dim outStream As New MemoryStream()
        Dim compressed As Byte() = New Byte(ms.Length - 1) {}
        ms.Read(compressed, 0, compressed.Length)
        Dim gzBuffer As Byte() = New Byte(compressed.Length + 3) {}
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length)
        System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4)
        res = Convert.ToBase64String(gzBuffer)
    Catch ex As Exception
        Log("mdl.zipString: " & ex.Message)
    End Try
    Return res
End Function

Public Function unzipString(ByVal compressedText As String) As String
    Dim res As String = ""
    Try
        Dim gzBuffer As Byte() = Convert.FromBase64String(compressedText)
        Using ms As New MemoryStream()
            Dim msgLength As Integer = BitConverter.ToInt32(gzBuffer, 0)
            ms.Write(gzBuffer, 4, gzBuffer.Length - 4)
            Dim buffer As Byte() = New Byte(msgLength - 1) {}
            ms.Position = 0
            Using zipStream As New System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Decompress)
                zipStream.Read(buffer, 0, buffer.Length)
            End Using
            res = System.Text.Encoding.UTF8.GetString(buffer, 0, buffer.Length)
        End Using
    Catch ex As Exception
        Log("mdl.unzipString: " & ex.Message)
    End Try
    Return res
End Function

这并没有回答问题,因为这段代码不适用于Android。我建议将其删除。 - Doron Yakovlev Golani
@DoronYakovlev-Golani,尽管语言有所改变,但这个答案的核心逻辑是否有价值?如果有的话,我会使用“踩”功能吗?Meta 论坛上对此有何建议? - Shawn
@Shawn 我认为这个回答试图回答“如何在VB中压缩/解压缩”字符串的问题?这并没有回答被问到的问题(该问题仅涉及Android),作为一个SO用户,我不希望看到它与这个问题有关。 - Doron Yakovlev Golani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接