1

I would like to convert some ints and some strings into a single byte array and then back again. I've done a bit of research on how to do converting, but I'm not sure if its all correct.

Converting a string to a byte array is easy:
byte[] bytes = string.getBytes();

Converting it back again via Arrays.toString() because that just creates a string of the bytes.

Does this work: String s = new String(bytes);?

Converting ints to byte array is like this:

int[] data = { int1, int2, int3 }; 
ByteBuffer byteBuffer = ByteBuffer.allocate(data.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(data);
byte[] my_app_state = byteBuffer.array();

But I don't know how to convert it back again.

My aim is to have say 4 ints and 2 strings converted to a single byte array and then convert them back again.

For example. I have these objects and would like them to converted to the same byte array.

int int1 = 1;
int int2 = 2;
int int3 = 3;
int int4 = 4;
String s1 = "mystring1"
String s2 = "mystring2"

Update: Removed code where I thought there was a problem. There wasn't.

  • 1
    If you catch an exception, there is no point printing it and pretending it didn't happen. You code will be simpler if you don't catch the IOException, unless you know what to do with it. – Peter Lawrey Feb 23 '14 at 09:54

3 Answers3

3

For each operation, you need to determine the reverse operation, not just any operation which returns the right type. for example, the reverse of n * 2 is m / 2 not m - 2 even though the type is right.

Arrays.toString("Hi".getBytes()) => "{ 72, 105 }"

So you can do

text.getBytes() => new String(bytes) // if the same character encoding is used.

a better option is

text.getBytes("UTF-8") => new String(bytes, "UTF-8");

The problem with an array is you have two pieces of information a length and some bytes If you just write the bytes, you no longer know the length and so you can't easily decode it (perhaps impossible)

In your case, the simplest option is to use a Data Stream

// buffer which grows as needed.
ByteArrayOutputStream boas = new ByteArrayOutputStream();
// supports basic data types
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(data.length);
for(int i: data) dow.writeInt(i);
// write the length of the string + the UTF-8 encoding of the text.
dos.writeUTF(s1);
dos.writeUTF(s2);
byte[] bytes = bytes.toByteArray();

To do the reverse, you use the InputStream and the readXxxx instead of writeXxxx methods.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Could you also show an example for the reverse please? Will the data still be in the same order as it is important for me to know which object is which. –  Feb 23 '14 at 09:15
  • 1
    Yes, the order will be preserved. If you write one int and one string, you should read one int and one string. You should read the javadoc now that you know which classes you can use. – JB Nizet Feb 23 '14 at 09:19
  • Thanks. Also, should it be `baos.toByteArray();` rather than `bytes`? –  Feb 23 '14 at 09:21
  • @JBNizet I've been trying this answer, but I'm having problems. I've updated the question with the code I'm trying. –  Feb 23 '14 at 09:46
  • 1
    @RiThBo: you're writing one int to the stream, which is the **length** of the data array, which is 3. So obviously, when reading the int from the stream, you get back 3. – JB Nizet Feb 23 '14 at 09:50
  • @RiThBo You get back the same integers you wrote in the order you wrote them. There is no magic here. If you wrote a length, you have to read the length first, create an `int[]` for that length and read the values into it in a loop. – Peter Lawrey Feb 23 '14 at 09:53
1

Java makes it very simple to achieve this, as this is a very common use case. What you need looks very much like Serialization.

Serialization works like this: A single object can be converted to a set of bytes and stored in a byte array (usually for writing to a file or sending over a network).

The good things is that any object can become serializable by just implementing a marker interface (just 1 line of code). Also, all Wrapper datatypes and String and Collections objects like ArrayList are serializable.

Coming to your question: Put all your data in a single object and serialize that object. 3 options come to my mind: 1. An Object[] or ArrayList (if you know the order for sure, so that you can access based on position) 2. A HashMap, (if you can assign a name to each of them instead of relying on position) 3. Create your own data type with fields like int1, int2 or even more meaningful names. (Your class should implement Serializable).

Now, all your data is added into a single object. Convert this one object to a byte array and your job is done.

Check this link for how to convert a single object to byte array: Java Serializable Object to Byte Array

    Object[] payload = new Object[]{int1, int2, int3, int4, string1, string2};
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(out);
    os.writeObject(payload);
    byte[] result = out.toByteArray(); //Done
Community
  • 1
  • 1
Teddy
  • 4,009
  • 2
  • 33
  • 55
0

for store Strings as well you have to use some thing like

IntBuffer intBuffer = byteBuffer.asIntBuffer();
CharBuffer stringBuffer = byteBuffer.asCharBuffer();

then you have to traverse the loop on char[][] string = {s1.toCharArray(),s2.toCharArray()}; to put the each character in stringBuffer and more thing you have to do is you to make your byteBuffer to sufficient to hold these values my friend

Girish
  • 1,717
  • 1
  • 18
  • 30
  • I suggest you try this because you will create as many problems as you solve. for example, the position won't be right and the length won't be stored. – Peter Lawrey Feb 23 '14 at 09:03
  • 1
    @Peter Lawrey, yes he has to increase the position thanks for remind me – Girish Feb 23 '14 at 09:10