Decompress string in java from compressed string i

2019-06-05 12:34发布

I was searching for the correct solution to decompress the string in java coming from c# code.I tried myself with lot of techniques in java like(gzip,inflatter etc.).but didn't get the solution.i got some error while trying to decompress the string in java from compressed string from c# code.

My C# code to compress the string is,

public static string CompressString(string text)
{

   byte[] byteArray = Encoding.GetEncoding(1252).GetBytes(text);//  Encoding.ASCII.GetBytes(text);

   using (var ms = new MemoryStream())
   {
    // Compress the text
    using (var ds = new DeflateStream(ms, CompressionMode.Compress))
    {
     ds.Write(byteArray, 0, byteArray.Length);
    }

    return Convert.ToBase64String(ms.ToArray());
   }
  }

And decompress the string in java using,

private static void compressAndDecompress(){
    try {
        // Encode a String into bytes
        String string = "xxxxxxSAMPLECOMPRESSEDSTRINGxxxxxxxxxx";
        // // Compress the bytes
        byte[] decoded = Base64.decodeBase64(string.getBytes());
        byte[] output = new byte[4096];
        // Decompress the bytes
        Inflater decompresser = new Inflater();
        decompresser.setInput(decoded);

        int resultLength = decompresser.inflate(output);
        decompresser.end();

        // Decode the bytes into a String
        String outputString = new String(output, 0, resultLength, "UTF-8");

        System.out.println(outputString);
    } catch(java.io.UnsupportedEncodingException ex) {    
        ex.printStackTrace();
    } catch (java.util.zip.DataFormatException ex) {
        ex.printStackTrace();
    }
}

I get this exception when running the above code:

java.util.zip.DataFormatException: incorrect header check

Kindly give me the sample code in java to decompress the string java.Thanks

3条回答
Root(大扎)
2楼-- · 2019-06-05 13:24

My C# code to compress is

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

Java code to decompress the text is

private String Decompress(String compressedText)
{

    byte[] compressed = compressedText.getBytes("UTF8");
    compressed = org.apache.commons.codec.binary.Base64.decodeBase64(compressed);
    byte[] buffer=new byte[compressed.length-4];
    buffer = copyForDecompression(compressed,buffer, 4, 0);
    final int BUFFER_SIZE = 32;
    ByteArrayInputStream is = new ByteArrayInputStream(buffer);
    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();
}
private  byte[] copyForDecompression(byte[] b1,byte[] b2,int srcoffset,int dstoffset)
{       
    for(int i=0;i<b2.length && i<b1.length;i++)
    {
        b2[i]=b1[i+4];
    }
    return b2;
}

This code works perfectly fine for me.

查看更多
Melony?
3楼-- · 2019-06-05 13:25

For beloved googlers,

As @dbw mentioned,

according to post How to decompress stream deflated with java.util.zip.Deflater in .NET?, java.util.zip.deflater equivalent in c# the default deflater used in C# is not having any java equivalent that's why users prefer Gzip, Ziplib or some other zip techniques.

a relatively simple method would be using GZip. And for the accepted answer, one problem is that in this method you should append the data size to the compressed string yourself, and more importantly as per my own experience in our production app, It is buggy when the string reaches ~2000 chars!

the bug is in the System.io.Compression.GZipStream

any way using SharpZipLib in c# the problem goes away and everything would be as simple as following snippets:

JAVA:

import android.util.Base64;

import com.google.android.gms.common.util.IOUtils;

import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class CompressionHelper {

    @Nullable
    public static String compress(@Nullable String data) {
        if(data == null || data.length() == 0)
            return null;
        try {

            // Create an output stream, and a gzip stream to wrap over.
            ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
            GZIPOutputStream gzip = new GZIPOutputStream(bos);

            // Compress the input string
            gzip.write(data.getBytes());
            gzip.close();
            byte[] compressed;
            // Convert to base64
            compressed = Base64.encode(bos.toByteArray(),Base64.NO_WRAP);
            bos.close();
            // return the newly created string
            return new String(compressed);
        } catch(IOException e) {

            return null;
        }
    }


    @Nullable
    public static String decompress(@Nullable String compressedText) {
        if(compressedText == null || compressedText.length() == 0)
            return null;
        try {
            // get the bytes for the compressed string
            byte[] compressed = compressedText.getBytes("UTF-8");

            // convert the bytes from base64 to normal string
            compressed = Base64.decode(compressed, Base64.NO_WRAP);

            ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
            GZIPInputStream gis = new GZIPInputStream(bis);
            byte[] bytes = IOUtils.toByteArray(gis);
            return new String(bytes, "UTF-8");

        }catch (IOException e){
            e.printStackTrace();
        }

        return null;
    }

}

and c#:

using ICSharpCode.SharpZipLib.GZip; //PM> Install-Package SharpZipLib
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GeneralTools
{
    public static class CompressionTools
    {
        public static string CompressString(string text)
        {
            if (string.IsNullOrEmpty(text))
                return null;
            byte[] buffer = Encoding.UTF8.GetBytes(text);
            using (var compressedStream = new MemoryStream())
            {
                GZip.Compress(new MemoryStream(buffer), compressedStream, false);
                byte[] compressedData = compressedStream.ToArray();
                return Convert.ToBase64String(compressedData);
            }
        }


        public static string DecompressString(string compressedText)
        {
            if (string.IsNullOrEmpty(compressedText))
                return null;
            byte[] gZipBuffer = Convert.FromBase64String(compressedText);
            using (var memoryStream = new MemoryStream())
            {
                using (var compressedStream = new MemoryStream(gZipBuffer))
                {
                    var decompressedStream = new MemoryStream();
                    GZip.Decompress(compressedStream, decompressedStream, false);

                    return Encoding.UTF8.GetString(decompressedStream.ToArray()).Trim();
                }
            }
        }


    }

}

you may also find the codes here

查看更多
虎瘦雄心在
4楼-- · 2019-06-05 13:41

Had exactly the same issue. Could solve it via

byte[] compressed = Base64Utils.decodeFromString("mybase64encodedandwithc#zippedcrap");
Inflater decompresser = new Inflater(true);
decompresser.setInput(compressed);
byte[] result = new byte[4096];
decompresser.inflate(result);
decompresser.end();
System.out.printf(new String(result));

The magic happens with the boolen parameter on instantiating the Inflator

BW Hubert

查看更多
登录 后发表回答