Is this the recommended way to get the bytes from the ByteBuffer
ByteBuffer bb =..
byte[] b = new byte[bb.remaining()]
bb.get(b, 0, b.length);
Depends what you want to do.
If what you want is to retrieve the bytes that are remaining (between position and limit), then what you have will work. You could also just do:
ByteBuffer bb =..
byte[] b = new byte[bb.remaining()];
bb.get(b);
which is equivalent as per the ByteBuffer javadocs.
Note that the bb.array() doesn't honor the byte-buffers position, and might be even worse if the bytebuffer you are working on is a slice of some other buffer.
I.e.
byte[] test = "Hello World".getBytes("Latin1");
ByteBuffer b1 = ByteBuffer.wrap(test);
byte[] hello = new byte[6];
b1.get(hello); // "Hello "
ByteBuffer b2 = b1.slice(); // position = 0, string = "World"
byte[] tooLong = b2.array(); // Will NOT be "World", but will be "Hello World".
byte[] world = new byte[5];
b2.get(world); // world = "World"
Which might not be what you intend to do.
If you really do not want to copy the byte-array, a work-around could be to use the byte-buffer's arrayOffset() + remaining(), but this only works if the application supports index+length of the byte-buffers it needs.
As simple as that
private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
byte[] bytesArray = new byte[byteBuffer.remaining()];
byteBuffer.get(bytesArray, 0, bytesArray.length);
return bytesArray;
}
final ByteBuffer buffer;
if (buffer.hasArray()) {
final byte[] array = buffer.array();
final int arrayOffset = buffer.arrayOffset();
return Arrays.copyOfRange(array, arrayOffset + buffer.position(),
arrayOffset + buffer.limit());
}
// do something else
If one does not know anything about the internal state of the given (Direct)ByteBuffer and wants to retrieve the whole content of the buffer, this can be used:
ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);
This is a simple way to get a byte[], but part of the point of using a ByteBuffer is avoiding having to create a byte[]. Perhaps you can get whatever you wanted to get from the byte[] directly from the ByteBuffer.
Related
I am trying to use ByteBuffer properly with BigEndian byte order format..
I have couple of fields which I am trying to put together into a single ByteBuffer before storing it in Cassandra database.
That Byte Array which I will be writing into Cassandra is made up of three Byte Arrays as described below-
short employeeId = 32767;
long lastModifiedDate = "1379811105109L";
byte[] attributeValue = os.toByteArray();
Now, I will write employeeId , lastModifiedDate and attributeValue together into a single Byte Array and that resulting Byte Array I will write into Cassandra and then I will be having my C++ program which will retrieve that Byte Array data from Cassandra and then deserialize it to extract employeeId , lastModifiedDate and attributeValue from it.
So to do this, I am using ByteBuffer with BigEndian byte order format.
I have put up this code together -
public static void main(String[] args) throws Exception {
String text = "Byte Buffer Test";
byte[] attributeValue = text.getBytes();
long lastModifiedDate = 1289811105109L;
short employeeId = 32767;
int size = 2 + 8 + 4 + attributeValue.length; // short is 2 bytes, long 8 and int 4
ByteBuffer bbuf = ByteBuffer.allocate(size);
bbuf.order(ByteOrder.BIG_ENDIAN);
bbuf.putShort(employeeId);
bbuf.putLong(lastModifiedDate);
bbuf.putInt(attributeValue.length);
bbuf.put(attributeValue);
bbuf.rewind();
// best approach is copy the internal buffer
byte[] bytesToStore = new byte[size];
bbuf.get(bytesToStore);
// write bytesToStore in Cassandra...
// Now retrieve the Byte Array data from Cassandra and deserialize it...
byte[] allWrittenBytesTest = bytesToStore;//magicFunctionToRetrieveDataFromCassandra();
ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest);
bb.order(ByteOrder.BIG_ENDIAN);
bb.rewind();
short extractEmployeeId = bb.getShort();
long extractLastModifiedDate = bb.getLong();
int extractAttributeValueLength = bb.getInt();
byte[] extractAttributeValue = new byte[extractAttributeValueLength];
bb.get(extractAttributeValue); // read attributeValue from the remaining buffer
System.out.println(extractEmployeeId);
System.out.println(extractLastModifiedDate);
System.out.println(new String(extractAttributeValue));
}
Is there any better way of doing this, the way I am doing it currently? Or some minor improvements that we can do it here??
This is the first time I am using ByteBuffer so having little bit problem...
Can anyone take a look and let me know whether this is the right way to use ByteBuffer?
The default order is always BIG_ENDIAN, so you don't meed to set it. Also when you wrap() is is already rewind()ed.
Instead of copying the underlying array, I would use the underlying array.
Replace
bbuf.rewind();
// best approach is copy the internal buffer
byte[] bytesToStore = new byte[size];
bbuf.get(bytesToStore);
with
byte[] bytesToStore = bbuf.array();
I had one question.
Is there library or etc to compose int & strings to byte array ?
Like :
byte temparray[] = new byte[10];
int a = 10;
int b = 10;
temparray << new String("12") << a << b;
Thanks.
edit
byte[] buffer = new byte[649];
byte[] charname = this.getName().getBytes();
System.arraycopy(charname, 0 , buffer, 0, charname.length);
for(int i=0;i<16;i++) //mystery crs 16 zeros
{
buffer[i+17] = (byte)0x30;
}
buffer[34] = this.faction;
if(this.characterClass == 2)
{
buffer[40] = 2;
} else
{
buffer[40] = 1;
}
System.arraycopy(BitTools.shortToByteArray(face), 0, buffer, 42, 2);
buffer[44] = 1;
buffer[48] = (byte)this.characterClass; //class byte
buffer[52] = 2; explanation yet
buffer[54] = (byte)this.getLevel();
This is an example of my packet generator and i wanted to simplify it, but in packet i use only shorts, ints and strings.
java.io.ByteArrayOutputStream is a stream implementation that collects content on an internal byte array, and you can wrap it in a java.io.OutputStreamWriter to write character content to it.
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
Writer out = new OutputStreamWriter(byteOut, "UTF-8"); // Uses UTF-8 encoding
out.write("12");
out.write(10);
out.write(10);
out.close();
byte[] bytes = byteOut.toByteArray();
After this, bytes.length is just long enough for the bytes written to byteOut.
Yes. See java.io.ByteArrayOutputStream. Note that you can wrap this stream to support writing of other types like String: PrintWriter pw = new PrintWriter(yourByteArrayOutputStream); pw.print("Hello");
And afterwards use yourByteArrayOutputStream.toByteArray(); to get the byte array.
http://docs.oracle.com/javase/7/docs/api/
Integer.byteValue();
Double.byteValue();
String.getBytes();
// etc.
Take a look at String#getBytes and ByteBuffer. Charsets and byte order might be important depending on your use case.
I've been searching for a way to convert a FloatBuffer array to a byte array. I have found a way to convert a FloatBuffer object to byte[]:
convert from floatbuffer to byte[]
But after searching the Internet for several hours I haven't been able to find something equivalent to convert from FloatBuffer[].
And to do the inverse, to convert from byte[] to FloatBuffer[], I've only found this:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(floatBufferObject);
byte [] descriptorsBytes = bos.toByteArray();
But it seems a little strange there is not a simpler way to do this.
Maybe I'm missing something very obvious, maybe I should convert the FloatBuffer array to other type that is simpler to convert to a byte array?
Do you want one FloatBuffer, or multiple?
To convert from a FloatBuffer to a byte[], you could do something like
FloatBuffer input;
byte[] output = new byte[input.capacity() * 4];
ByteBuffer.wrap(output).asFloatBuffer().put(input);
The other direction would just be
ByteBuffer.wrap(byteArray).asFloatBuffer()
You already had the answer on how to convert one FloatBuffer into a byte array, so simply extend that to convert an array of them:
final FloatBuffer[] floatBuffers = new FloatBuffer[] {...};
final ByteBuffer byteBuffer = ByteBuffer.allocate(sumOfFloatBufferCapacities) * 4);
final FloatBuffer floatBufView = byteBuffer.asFloatBuffer();
for (final FloatBuffer fBuf : floatBuffers) {
floatBufView.put(fBuf);
}
byte[] data = byteBuffer.array();
The above is pseudocode, you can adapt it to your needs.
Convert FloatBuffer[] to byte[]:
FloatBuffer[] buffers = ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for (FloatBuffer fb : buffers) {
ByteBuffer byteBuffer = ByteBuffer.allocate(fb.capacity() * 4);
byteBuffer.asFloatBuffer().put(fb);
bos.write(byteBuffer.array());
}
byte[] ba = bos.toByteArray();
I wonder how you should do if you are going to convert an String that contains an array of bytes, actually bytes from an image into an byte array.
I guess this is a pretty common issue so i guess someone could give any suggestions.
If it is better to convert an JSONArray into an byte array i would like to know why.
I wonder how you should do if you are going to convert an String that contains an array of bytes, actually bytes from an image into an byte array.
It depends on how you've constructed the string in the first place. If something somewhere has used
new String(imageData)
then you've already lost information, potentially. Image data isn't text.
To propagate opaque binary data in text, you should use base64 (or potentially hex). Android already has a Base64 class that makes this easy:
String text = Base64.encodeToString(originalBytes, Base64.DEFAULT);
...
byte[] roundTrip = Base64.decode(text, Base64.DEFAULT);
EDIT: If you can't use that class, this public domain base64 encoder should work fine.
Byte[] to String
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Your_Bitmap.compress(CompressFormat.PNG, 0 , baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
String bytetostring = Base64.encodeToString(b, Base64.DEFAULT);
return bytetostring ;
String to Byte[]
byte[] data = Base64.decode("Your string", Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data.length);
I have a byte array I want to assign as follows:
First byte specifies the length of the string: (byte)string.length()
2nd - Last bytes contain string data from string.getBytes()
Other than using a for loop, is there a quick way to initialize a byte array using bytes from two different variables?
You can use System.arrayCopy() to copy your bytes:
String x = "xx";
byte[] out = new byte[x.getBytes().length()+1];
out[0] = (byte) (0xFF & x.getBytes().length());
System.arraycopy(x.getBytes(), 0, out, 1, x.length());
Though using something like a ByteArrayOutputStream or a ByteBuffer like other people suggested is probably a cleaner approach and will be better for your in the long run :-)
How about ByteBuffer ?
Example :
ByteBuffer bb = ByteBuffer.allocate(string.getBytes().length +1 );
bb.put((byte) string.length());
bb.put(string.getBytes());
While ByteBuffer is generally the best way to build up byte arrays, given the OP's goals I think the following will be more robust:
public static void main(String[] argv)
throws Exception
{
String s = "any string up to 64k long";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos);
out.writeUTF(s);
out.close();
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(bis);
String s2 = in.readUTF();
}
How about ByteArrayOutputStream?