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();
Related
I have used the ByteArrayOutputStream which is very useful but for my needs the limits are too great (ie I am dealing with numbers in the range +-32,768)
Here is the code where I would use it:
ByteArrayOutputStream leftStream = new ByteArrayOutputStream();
ByteArrayOutputStream rightStream = new ByteArrayOutputStream();
while (din.read(temp, 0, 4) != -1) {
if (decodedFormat.getChannels() == 2) {
leftStream.write(temp[1] * 256 + temp[0]);
rightStream.write(temp[3] * 256 + temp[2]);
}
}
byte[] left = leftStream.toByteArray();
byte[] right = rightStream.toByteArray();
However the ByteArrayInputStream does not allow for values over 127 or under 128. Is there an equivalent ShortArrayOutputStream that allows shorts? Or do I have to make one myself somehow?
Yes, Use the DataOutputStream:
ByteArrayOuputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeShort(val);
This works even on embedded java devices with low java version 1.3
To read in use:
ByteArrayInputStream and DataInputStream dis, and dis.readShort():
...
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
DataInputStream dis = new DataInputStream(bis);
short val = dis.readShort();
You can wrap the ByteArrayOutputStream into DataOutputStream:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
dataOutputStream.writeShort(someShortValue);
What do you want to do?
Write out short data to a byte array?
Then wrap your byte array output stream with a DataOutputStream which has methods to writeShort(), writeInt() etc. Warning. I think the endian of DataOutputStream is BIG endian so if you want to use little endian you either have to write it yourself or use the other option:
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream dataout = new DataOutputStream(byteOut)
dataout.writeShort(shortValue);
Write a short[]
the easiest is to create a ByteBuffer, then use the asShortBuffer() method to view it as a ShortBuffer. the ShortBuffer has a put(short) and put(short[]);
If you want to write out the short data in Little endian, ByteBuffer has a method asOrder(ByteOrder) which can change the endian of the data it is reading or writing.
//NOTE length should be 2* num shorts since we allocate in bytes
ByteBuffer buf = ByteBuffer.allocate(length);
ShortBuffer shortBuf = buf.asShortBuffer();
shortBuf.put(shortValue);
shortBuf.put(shortArray);
getting data out from buffers is annoying. There are optional array() methods but not all buffer impelmentations support them so you have to do the following:
//once all data written to buffer
shortBuf.flip();
short[] dataOut = new short[shortBuf.remaining()];
shortBuf.get(dataOut);
Combination of both to use a ShortBuffer on an unknown input size
If you don't know how many bytes you will write, and you don't have a reasonable, max length, then you may need to do a combination of both options. First, use option #1 to dynamically grow a byte buffer by writing shorts to it. Then convert the byte[] to a short[] with the ShortBuffer.
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream dataout = new DataOutputStream(byteOut)
dataout.writeShort(shortValue);
...
ShortBuffer buf =ByteBuffer.wrap(byteOut.toByteArray())
.asShortBuffer();
int length = buf.remaining();
short[] asShorts = new short[length];
buf.get(asShorts);
It's not pretty and uses 2x the memory since you make a copy of the array.
Create a ObjectOutputStream. This has a writeShort (http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html#writeShort(int)) method.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeShort(123);
...
I capture song in real-time with TargetDataLine:
line.read(buffer, 0, buffer.length);
But this buffer have to be byte array. I need capture to buffer which is long array or float array. I try to convert from byte to long or float but these data are not correct.
How Can I capture with another type or covert byte to float/long in correct way?
You could try this approach:
byte[] buffer = new byte[2048];
float[] fBuffer = new float[buffer.length >> 2];
ByteBuffer bb = ByteBuffer.wrap(buffer);
FloatBuffer fb = bb.asFloatBuffer();
fb.get(fBuffer, 0, fBuffer.length);
This does the conversion for you.
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 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?
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.