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.
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.
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
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
Related
This question already has answers here:
Convert a string representation of a hex dump to a byte array using Java?
(25 answers)
Closed 8 years ago.
I have a string which I want to cast to a byte array, however, my string is the actually representation of an image byte array (eg. String x = "00123589504e47..."). So, I'm stuck because doing x.getBytes(); doesn't do the job.. I need a way to cast the string to byte array and then save that byte array to an image in a specific directory. How can I cast it?
doing x.getBytes(); doesn't do the job
Yes, that's normal...
A char and a byte have no relationship to one another; you cannot seamlessly cast from one to the other and expect to obtain a sane result. Read about character codings.
From what you want, it appears that the String is in fact a "hex dump" of the image. You therefore need to read two chars by two chars and convert that to a byte array.
How? Well, you have hints. First, the length of the resulting byte array will always be that of the string divided by 2, so you can do that to start with:
// input is the string
final int arrayLen = input.length() / 2;
final byte[] result = new byte[arrayLen];
Then you need to walk through the string's characters and parse those two characters into a byte, and add that to the array:
int strIndex;
char[] chars = new char[2];
for (int arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++) {
strIndex = 2 * arrayIndex;
chars[0] = input.charAt(strIndex);
chars[1] = input.charAt(strIndex + 1);
result[arrayIndex] = Byte.parseByte(new String(chars), 16);
}
// Done
return result;
I always use this one liner:
byte[] data = DatatypeConverter.parseHexBinary(x);
You can then instantiate a FileOutputStream for the image and write the bytes onto that.
I'm parsing a byte array which contains variables of different types. I'm getting this array from HID connected to my phone. Array was made by C programmer. I'm trying to parse it using ByteBuffer class:
byte[] buffer = new byte[64];
if(connection.bulkTransfer(endpoint, buffer, 64, 1000) >= 0)
{
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
char mId = byteBuffer.getChar();
short rId = byteBuffer.getShort();
// ............................
}
But the values of this variables are not correct. Can anyone please tell me what i'm doing wrong?
There are systems with LitteEndian Byte order and BigEndian.
java uses BigEndian.
If the c programmer wrote the byte array in Little endian, you could use DataInputStream based on an Appache LittleEndianInputStream:
LittleEndianInputStream leis = new LittleEndianInputStream(is);
DataInputStream dis = new DataInputStream(leis);
int i1 = dis.readInt();
short s2 = dis.readShort();
If you and your colleague define a binary interface (file, or byte array) you always should force a speciifc byte order (Either little or big endian).
If byte order (little vs big endian) is the issue, you can set the byte order for the ByteBuffer to native without changing all of the program:
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
byteBuffer.order(ByteOrder.nativeOrder()); // Set native byte order
char mId = byteBuffer.getChar();
short rId = byteBuffer.getShort();
On the other hand, if you find ByteBuffer objects more convenient than byte arrays, tell the C programmer to return you a direct byte buffer instead of an array: easier for all parties and probably more efficient.
I would like to transform a Java String str into byte[] b with the following characteristics:
b is a valid C string (ie it has b.length = str.length() + 1 and b[str.length()] == 0.
the characters in b are obtained by converting the characters in str to 8-bit ASCII characters.
What is the most efficient way to do this — preferably an existing library function? Sadly, str.getBytes("ISO-8859-1") doesn't meet my first requirement...
// do this once to setup
CharsetEncoder enc = Charset.forName("ISO-8859-1").newEncoder();
// for each string
int len = str.length();
byte b[] = new byte[len + 1];
ByteBuffer bbuf = ByteBuffer.wrap(b);
enc.encode(CharBuffer.wrap(str), bbuf, true);
// you might want to ensure that bbuf.position() == len
b[len] = 0;
This requires allocating a couple of wrapper objects, but does not copy the string characters twice.
You can use str.getBytes("ISO-8859-1") with a little trick at the end:
byte[] stringBytes=str.getBytes("ISO-8859-1");
byte[] ntBytes=new byte[stringBytes.length+1];
System.arraycopy(stringBytes, 0, ntBytes, 0, stringBytes.length);
arraycopy is relatively fast as it can use native tricks and optimizations in many cases. The new array is filled with null bytes everywhere we didn't overwrite it(basically just the last byte).
ntBytes is the array you need.
In past I haven't done much of byte shifting so I'm a bit loss here. Basically I have double array of size 26 and I should send the array in one UDP packet in Java. I found some examples of how to convert one double to bytearray, but I'm not sure how to apply it to double-array.
So how this should be done? Loop through the double array and convert each double and somehow concatenating them to one bytearray?
Convert your doubles into a byte array using java.nio.ByteBuffer
ByteBuffer bb = ByteBuffer.allocate(doubles.length * 8);
for(double d : doubles) {
bb.putDouble(d);
}
get the byte array
byte[] bytearray = bb.array();
send it over the net and then convert it to double array on the receiving side
ByteBuffer bb = ByteBuffer.wrap(bytearray);
double[] doubles = new double(bytearray.length / 8);
for(int i = 0; i < doubles.length; i++) {
doubles[i] = bb.getDouble();
}
So how this should be done? Loop through the double array and convert each double and somehow concatenating them to one bytearray?
Exactly. You can make use of DoubleBuffer, perhaps. (Marko linked it in his comment)
What Marko referred to was having actually a ByteBuffer and fetching a "DoubleBuffer"-View to it. So you can put the Doubles into the DoubleBuffer View and fetch the byte[] from the original ByteBuffer.
apache httpcore provides a org.apache.http.util.ByteArrayBuffer class which my be helpful
ByteArrayBuffer buffer = new ByteArrayBuffer(26);
buffer.append(...)
How can I split a variable into single bytes in java? I have for example following snippet in C++:
unsigned long someVar;
byte *p = (byte*)(void*) someVar; // byte being typedef unsigned char (from 0 to 255)
byte *bytes = new byte[sizeof(someVar)];
for(byte i = 0;i<sizeof(someVar);i++)
{
bytes[i] = *p++;
}
.... //do something with bytes
I want to accomplish the same under java, but I can't seem to find an obvious workaround.
There are two ways to do it with the ByteBuffer class. One is to create a new byte array dynamically.
long value = 123;
byte[] bytes = ByteBuffer.allocate(8).putLong(value).array();
Another is to write to an existing array.
long value = 123;
byte[] bytes = new byte[8];
ByteBuffer.wrap(bytes).putLong(value);
// bytes now contains the byte representation of 123.
If you use Guava, there is a convenience Longs.toByteArray. It is simply a wrapper for John's ByteBuffer answer above, but if you already use Guava, it's slightly "nicer" to read.