How to represent data in one byte array using Byte Buffer? - java

I have my below layout in which I need to represent my data and then finally I need to make one byte array out of that.
// below is my data layout -
// data key type which is 1 byte
// data key len which is 1 byte
// data key (variable size which is a key_len)
// timestamp (sizeof uint64_t)
// data size (sizeof uint16_t)
// data (variable size = data size)
So I started like this but I am having some confusion so got stuck -
// data layout
byte dataKeyType = 101;
byte dataKeyLength = 3;
// not sure how to represent key here
long timestamp = System.currentTimeMillis(); // which is 64 bit
short dataSize = 320; // what does this mean? it means size of data is 320 bytes?
// and now confuse as well how to represent data here, we can have any string data which can be converted to bytes
// and then make final byte array out of that
How do I represent this in one byte array using Byte Buffer? Any simple example will help me to understand better.

byte keyType = 101;
byte keyLength = 3;
byte[] key = {27, // or whatever your key is
55,
111};
long timestamp = System.currentTimeMillis();
// If your data is just a string, then you could do the following.
// However, you will likely want to provide the getBytes() method
// with an argument that specifies which text encoding you are using.
// The default is just the current platform's default charset.
byte[] data = "your string data".getBytes();
short dataSize = (short) data.length;
int totalSize = (1 + 1 + keyLength + 8 + 2 + dataSize);
ByteBuffer bytes = ByteBuffer.allocate(totalSize);
bytes.put(keyType);
bytes.put(keyLength);
bytes.put(key);
bytes.putLong(timestamp);
bytes.putShort(dataSize);
bytes.put(data);
// If you want everthing as a single byte array:
byte[] byteArray = bytes.array();

You can use Java's DataOutputStream class to dynamically generate the byte array. For example:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeByte(keyType);
dos.writeByte(keyLength);
dos.write(new byte[] { 1, 2, 3, ..., key_len-1 }, 0, key_len);
dos.writeLong(System.currentTimeMillis());
dos.writeShort(320);
dos.write(new byte[] { 1, 2, 3, ..., 319 }, 0, 320);
You should replace the two new byte[] {} parts by the array that contains the key bytes and the array that contains the data, respectively.

Related

storing an integer in a specific number of bytes in an array of bytes - JAVA

I'm trying to implement a database in java using slotted pages , so basically what I want to do is to store my data in a specific number of bytes .
so this is the page where I have to store it .
protected byte[] myData = new byte[PAGE_SIZE*1024]; //array for storing my data
now I want to store an Integer in the first 4 bytes of myData , when I do that automatically is stored in just one byte if the Integer doesn't exceed 255 , but what I want to do is use 4 bytes for my Integer it doesn't matter if it's 1 or one billion .
my question is , is it possible to do that in java ? to control how many bytes my data must allocate , like I assign 3 to the first 4 bytes of my byte array ?.
if (recordFitsIntoPage(record)) {
byte [] fix_rec = new byte [record.getFixedLength()];
byte [] var_rec= new byte [record.getVariableLength()];
var_rec = var_rec(record);
fix_rec = fix_rec(record);
byte [] box = { (byte) record.getVariableLength() ,(byte) offsetEnd };
System.arraycopy(fix_rec, 0,data,offset,record.getFixedLength());
System.arraycopy(var_rec, 0,data,offsetEnd,record.getVariableLength());
read_bytes(data);
this.numRecords++;
}else {
throw new Exception("no more space left");
}
I have a fixed-sized variables that I need to store them in my case for example in 12 bytes , I have been using System.arraycopy() but it's not relevant in my case , after I execute the code I get out of bound exception "last source index 12 out of bounds for byte[9]"
because it uses just 9 bytes to store my Data not 12 .
This method creates an array of 32 bytes of any integer given - be it 1 or one billion:
private static byte[] bigIntegerToBytes(BigInteger b, int numBytes) {
byte[] src = b.toByteArray();
byte[] dest = new byte[numBytes];
boolean isFirstByteOnlyForSign = src[0] == 0;
int length = isFirstByteOnlyForSign ? src.length - 1 : src.length;
int srcPos = isFirstByteOnlyForSign ? 1 : 0;
int destPos = numBytes - length;
System.arraycopy(src, srcPos, dest, destPos, length);
return dest;
}
You have an array of byte ready to store:
byte[] myData = new byte[PAGE_SIZE*1024];
You have a hand-picked integer as well:
BigInteger myInteger = new BigInteger("50000000000");
Then we change our integer to 32-length byte[]
byte[] bytesOfInteger = bigIntegerToBytes(myInteger,32);
Finally, you copy first 4 bytes of integer to your byte[] myData
System.arraycopy(bytesOfInteger, 0, myData, 0, 3);
So this shows that you can allocate any decent big integer into a fixed 32 byte[].

Why method for ByteBuffer putShort(value) does not working correctly in my case?

My task is convert short[] array to byte[] array, because need send bytes via socket. This is bytes for AudioTrack (Android)
For converting use this post, specifically this and this
This method gives only white noise, when try to convert short to byte array:
val sampleBuffer = decoder.decodeFrame(frameHeader, bitstream) as SampleBuffer
val pcm = sampleBuffer.buffer //pcm is short[] array
byteBuf = ByteBuffer.allocate(pcm.size * 2) // because 1 short = 2 bytes
while (pcm.size > i) {
byteBuf.putShort(pcm[i])
i++
}
auddioTrack.write(byteBuf.array(), 0, byteBuf.limit());
But this convert works fine:
var i = 0
val byteBuf = ByteBuffer.allocate(pcm.size * 2)
val buff = ByteBuffer.allocate(2)
//pcm size equals 2304
while (pcm.size > i) {
// byteBuf.putShort(pcm[i])
byteBuf.put(byteArrayOf((pcm[i].toInt() and 0x00FF).toByte(), ((pcm[i].toInt() and 0xFF00) shr (8)).toByte()))
i++
}
auddioTrack.write(byteBuf.array(), 0, byteBuf.limit());
Why has it happened?
byteBuf.array().size will return the size of the buffer (pcm.size * 2) regardless of whether that many bytes were written into the buffer. You probably want byteBuf.limit() instead.

Save the length and the value of a string into a byte

I need to save in the first byte position of the number of characters that has a string. Then store the value of each of the characters in the following positions.
String cadena = new String ("Desarrollo");
byte valores[] = new byte [cadena.length()];
valores = cadena.getBytes();
Use a java.nio.ByteBuffer. Get the String representation as a byte[] based on some given character set. Write the size of the String first as an int, then write the byte[].
String cadena = new String("Desarollo");
byte[] bytes = cadena.getBytes("UTF-8");
ByteBuffer buffer = ByteBuffer.allocate(4 + bytes.length); // 4 being the size of an int in bytes
buffer.putInt(cadena.length());
buffer.put(bytes);
You can then get the underlying byte[] with
buffer.array();
You should write the String length as an int because byte has a maximum value of 127, which you will probably surpass very fast.

How to use ByteBuffer properly?

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();

Java - is there something like binary stream?

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.

Categories

Resources