2

I have the following code to zip and unzip the String:

public static void main(String[] args) {
    // TODO code application logic here
    String Source = "hello world";
    byte[] a = ZIP(Source);
    System.out.format("answer:");
    System.out.format(a.toString());
    System.out.format("\n");


    byte[] Source2 = a.toString().getBytes();

    System.out.println("\nsource 2:" + Source2.toString() + "\n");

    String b = unZIP(Source2);
    System.out.println("\nunzip answer:");
    System.out.format(b);
    System.out.format("\n");


}

  public static byte[] ZIP(String source) {
      ByteArrayOutputStream bos= new ByteArrayOutputStream(source.length()* 4);

      try {
          GZIPOutputStream outZip= new GZIPOutputStream(bos);
          outZip.write(source.getBytes());
          outZip.flush();
          outZip.close();
      } catch (Exception Ex) {
      }
      return bos.toByteArray();
  }

public static String unZIP(byte[] Source) {
    ByteArrayInputStream bins= new ByteArrayInputStream(Source);
    byte[] buf= new byte[2048];
    StringBuffer rString= new StringBuffer("");
    int len;

    try {
        GZIPInputStream zipit= new GZIPInputStream(bins);
        while ((len = zipit.read(buf)) > 0) {
             rString.append(new String(buf).substring(0, len));
        }
        return rString.toString();
    } catch (Exception Ex) {
       return "";
    }
}

When "Hello World" have been zipped, it's will become [B@7bdecdec in byte[] and convert into String and display on the screen. However, if I'm trying to convert the string back into byte[] with the following code:

 byte[] Source2 = a.toString().getBytes();

the value of variable a will become to [B@60a1807c instead of [B@7bdecdec . Does anyone know how can I convert the String (a value of byte but been convert into String) back in byte[] in JAVA?

Jin Yong
  • 42,698
  • 72
  • 141
  • 187
  • 4
    This is not the value of the variable, it's its hashcode, like an identifier, use `Arrays.toString(byteArray)` to see the value – azro Dec 03 '18 at 21:04
  • You need to use a character encoding like ISO 8859 1 for creating the String and getting the bytes. – Peter Lawrey Dec 03 '18 at 21:06
  • Or, more likely, UTF-8: `str.getBytes(StandardCharsets.UTF_8)` (you can make that more readable with a static import). – David Conrad Dec 03 '18 at 21:12
  • 1
    Rule of thumb: always assume the default platform encoding is something horrifying, like EBCDIC, and act accordingly. – David Conrad Dec 03 '18 at 21:12
  • Related: https://stackoverflow.com/questions/14794930/why-does-printing-a-java-array-show-a-memory-location – Mark Rotteveel Dec 06 '18 at 15:31

2 Answers2

3

Why doing byte[] Source2 = a.toString().getBytes(); ?

It seems like a double conversion; you convert a byte[] to string the to byte[].

The real conversion of a byte[] to string is new String(byte[]) hoping that you're in the same charset.

Source2 should be an exact copy of a hence you should just do byte[] Source2 = a;

JFPicard
  • 5,029
  • 3
  • 19
  • 43
2

Your unzip is wrong because you are converting back a string which might be in some other encoding (let's say UTF-8):

public static String unZIP(byte[] source) throws IOException {
  ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length*2);
  try (ByteArrayInputStream in = new ByteArrayInputStream(source);
       GZIPInputStream zis = new GZIPInputStream(in)) {
    byte[] buffer = new buffer[4096];
    for (int n = 0; (n = zis.read(buffer) != 0; ) {
      bos.write(buffer, 0, n);
    }
  }
  return new String(bos.toByteArray(), StandardCharsets.UTF_8);
}

This one, not tested, will:

  • Store byte from the gzip stream into a ByteArrayOutputStream
  • Close the gzip/ByteArrayInputStream using try with resources
  • Convert the whole into a String using UTF-8 (you should always use encoding and unless rare case, UTF-8 is the way to go).

You must not use StringBuffer for two reasons:

  • The most important one: this will not behave well with multi bytes string such as UTF-8 or UTF-16.
  • And second, StringBuffer is synchronized: you should use StringBuilder whenever possible and whenever it should be used (eg: not here!). StringBuffer should be reserved for case where your share the StringBuffer with several threads, otherwise it is useless.

With those change, you will also need to change the ZIP as per David Conrad comment and because the unZIP use UTF-8:

public static byte[] ZIP(String source) throws IOException {
  ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length()* 4);
  try (GZIPOutputStream zip = new GZIPOutputStream(bos)) {
    zip.write(source.getBytes(StandardCharsets.UTF_8));
  }
  return bos.toByteArray();
}

As for the main, printing a byte[] will result in the default toString.

NoDataFound
  • 11,381
  • 33
  • 59