1

i have this relatively simple piece of Java (for Android) code which i have stripped down for this question.

int number = 42;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(number);
String serial = bos.toString("UTF-8");
os.close();

ByteArrayInputStream bis = new ByteArrayInputStream(serial.getBytes("UTF-8"));
ObjectInputStream is = new ObjectInputStream(bis);    // <<<< Exception Here

The last line, initializing the ObjectInputStream, throws a StreamCorruptedException and i have no idea why.

(i am planning to use this to serialize a few small objects to Strings and store them in SharedPreferences and read them back later. But i am using just an integer now because that isolates the problem)

cosmiczilch
  • 43
  • 2
  • 7
  • You're written a primitive as an Object ... that'll get autoboxed to `Integer` I believe (It must if it doesn't puke right there). Then ... you're trying to convert those bytes (which are a serialized `Integer` object) to a UTF-8 `String` ... I suspect that's not going to produce anything usable. – Brian Roach Jul 06 '13 at 20:58
  • I did try with os.writeInt(number) instead of os.writeObject(number) , and it still threw the same exception. So the problem is probably not in there.. Is there something wrong with trying to get a serialized string out of the ByteArrayOutputStream the way i'm doing it? – cosmiczilch Jul 06 '13 at 21:09

2 Answers2

2

The problem is the bytes to string and vice versa conversion. Try the following and it should work:

int number = 42;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(number);
os.close();

byte[] serial = bos.toByteArray();

ByteArrayInputStream bis = new ByteArrayInputStream(serial);
ObjectInputStream is = new ObjectInputStream(bis); 

For details take a look at how to convert byte array to string and vice versa

Community
  • 1
  • 1
René Link
  • 48,224
  • 13
  • 108
  • 140
2

The problem lies within the conversion itself. We can't expect to get the same byte array back if we convert it to and from a string using a char encoding.

Simple example:

byte[] expected = { -1, -2, -3, -4, -5 };
byte[] actual = new String(expected).getBytes();

// actual is now [-17, -65, -67, -17, -65, -67, -17, -65, -67]

So if you want to store a bytes in a String, use Base64 encoding:

int number = 42;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(number);
String serial = new BASE64Encoder().encode(bos.toByteArray());
os.close();

ByteArrayInputStream bis = new ByteArrayInputStream(new BASE64Decoder().decodeBuffer(serial));
ObjectInputStream is = new ObjectInputStream(bis);

(Can't tell if that class is available on android. So you might have to look for a different implementation)

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • Yep, this worked for me. Although the class is android.util.Base64. I'll just write it down here: `String serial = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT);` and, `ByteArrayInputStream bis = new ByteArrayInputStream(Base64.decode(serial, Base64.DEFAULT));` – cosmiczilch Jul 07 '13 at 01:06