welsh_boy
asked on
Sending A Long in a byte Array
I am trying to send a Long value that represents a filesize into a 128 byte data packet, the first byte is a header then I have reserved the next 8 bytes for the filesize.
I have done some research and found a class called BigInteger
http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigInteger.html
that does this.
My problem is knowing how many of the bytes to read back off at the other side, as If I read all 8 on a long value that doesnt fill all 8 then I get a wrong value, here is my code.
-------------
//Create Byte array and append to packet
BigInteger big = new BigInteger(Long.toString(f ileLength) );
byte[] testlong = new byte[8];
testlong = big.toByteArray();
String dickString = new String(testlong);
System.out.println(big.lon gValue() );//test to see if its seding the right value
//Copy to the packet
System.arraycopy(testlong, 0, testbuffer, 1, 8);
// I get an arrayindex Out Of Bounds error here
------------
//Read from packet
byte[] fileSize = new byte[8];
//read back the 8 bytes from the data packet
System.arraycopy(testbuffe r, 1, fileSize, 0, 8);
BigInteger big2 = new BigInteger(fileSize);
System.out.println(big2.lo ngValue() );
I can get it working with a small number eg 352, but I have to use 2 bytes instead of 8 to avoid the outofbounds exception.
Appreciate any help
I have done some research and found a class called BigInteger
http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigInteger.html
that does this.
My problem is knowing how many of the bytes to read back off at the other side, as If I read all 8 on a long value that doesnt fill all 8 then I get a wrong value, here is my code.
-------------
//Create Byte array and append to packet
BigInteger big = new BigInteger(Long.toString(f
byte[] testlong = new byte[8];
testlong = big.toByteArray();
String dickString = new String(testlong);
System.out.println(big.lon
//Copy to the packet
System.arraycopy(testlong,
// I get an arrayindex Out Of Bounds error here
------------
//Read from packet
byte[] fileSize = new byte[8];
//read back the 8 bytes from the data packet
System.arraycopy(testbuffe
BigInteger big2 = new BigInteger(fileSize);
System.out.println(big2.lo
I can get it working with a small number eg 352, but I have to use 2 bytes instead of 8 to avoid the outofbounds exception.
Appreciate any help
Sorry:
BigInteger big = new BigInteger.valueOf(fileLen gth);
byte[] testlong = big.toByteArray();
System.out.println(big.lo ngValue() );//test to see if its sending the right value
//Copy to the packet
System.arraycopy(testlong , 0, testbuffer, 0, 8);
BigInteger big = new BigInteger.valueOf(fileLen
byte[] testlong = big.toByteArray();
System.out.println(big.lo
//Copy to the packet
System.arraycopy(testlong
LOL, and the second index should be 1, not 0 (just saw the thing about the header). Make sure testbuffer.length >= 9
Use of BigInteger is a bit slow and unecessary.
You can use bit manipulation to handle converting bytes into long.
Here's an example of how to convert 4 bytes into an int, doing it for a long is a simple extension:
int ch1 = buf[0]
int ch2 = buf[1];
int ch3 = buf[2];
int ch4 = buf[3];
int = return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
Or alternatively use a DataInputStream wrapping a ByteArrayInputStream to handle it for you:
DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf)) ;
long l = in.readLong();
You can use bit manipulation to handle converting bytes into long.
Here's an example of how to convert 4 bytes into an int, doing it for a long is a simple extension:
int ch1 = buf[0]
int ch2 = buf[1];
int ch3 = buf[2];
int ch4 = buf[3];
int = return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
Or alternatively use a DataInputStream wrapping a ByteArrayInputStream to handle it for you:
DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf))
long l = in.readLong();
Similiar techniques can also be used for going the other direction.
It's only slow if it's perceptibly slow - and it almost certainly won't be. It's certainly more elegant and clearer.
More elegant and clear than:
long l = in.readLong();
I don't think so :)
long l = in.readLong();
I don't think so :)
I was talking about your first suggestion
ASKER
Here is my ammended code, I am still getting the error
--
//Declare the Data Packet
byte [] testbuffer=new byte [128];
//Set Header
testbuffer[0]=PacketCode.S FT;
//Copy File name at byte[9]
System.arraycopy(tester, 0, testbuffer, 9, tester.length);
BigInteger big = new BigInteger(Long.toString(f ileLength) );
byte[] testlong = big.toByteArray();
System.out.println("Long Send to Packet : " + big.longValue() );//test to see if its sending the right value
//Copy to the packet at position 1 - 8
System.arraycopy(testlong, 0, testbuffer, 1, 8); //<-- I get an out of bounds error here
//Read back long from the packet array
//Set up and empty 8 byte array
byte[] fileSize = new byte[8];
//Copy long back from the byte array pos 1-8
System.arraycopy(testbuffe r, 1, fileSize, 0, 8);
BigInteger big2 = new BigInteger(fileSize);
System.out.println("Read Long from Data Packet: " + big2.longValue() );
--
//Declare the Data Packet
byte [] testbuffer=new byte [128];
//Set Header
testbuffer[0]=PacketCode.S
//Copy File name at byte[9]
System.arraycopy(tester, 0, testbuffer, 9, tester.length);
BigInteger big = new BigInteger(Long.toString(f
byte[] testlong = big.toByteArray();
System.out.println("Long Send to Packet : " + big.longValue() );//test to see if its sending the right value
//Copy to the packet at position 1 - 8
System.arraycopy(testlong,
//Read back long from the packet array
//Set up and empty 8 byte array
byte[] fileSize = new byte[8];
//Copy long back from the byte array pos 1-8
System.arraycopy(testbuffe
BigInteger big2 = new BigInteger(fileSize);
System.out.println("Read Long from Data Packet: " + big2.longValue() );
DataOuputStream out = new DataOutputStream(new ByteArrayOutputStream(128) );
out.writeByte(PacketCode.S FT);
out.writeLong(fileLength);
out.write(tester);
byte [] testbuffer= out.toByteArray();
out.writeByte(PacketCode.S
out.writeLong(fileLength);
out.write(tester);
byte [] testbuffer= out.toByteArray();
And reading it back:
DataInputStream in = new DataInputStream(new ByteArrayInputStream(testb uffer));
byte packet = in.readByte();
long fileLength = in.readLong();
DataInputStream in = new DataInputStream(new ByteArrayInputStream(testb
byte packet = in.readByte();
long fileLength = in.readLong();
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
> byte[] testlong = big.toByteArray();
This will not necessarily return an 8 byte buffer. If you want to use this approach you will need to do:
System.arraycopy(testlong, 0, testbuffer, 1, testlong.length);
This will not necessarily return an 8 byte buffer. If you want to use this approach you will need to do:
System.arraycopy(testlong,
Actually thats not right either, should be:
System.arraycopy(testlong, 0, testbuffer, 1+(8-testlong.length), testlong.length);
Lot simpler to use DataOutput :)
System.arraycopy(testlong,
Lot simpler to use DataOutput :)
ASKER
cheers objects but the DataOutputStream doesnt seem to have a toByteArray() method
Im running Java 1.31
I have looked for the javadocs
http://java.sun.com/j2se/1.3/ja/docs/ja/api/java/io/DataOutputStream.html
any ideas??
Im running Java 1.31
I have looked for the javadocs
http://java.sun.com/j2se/1.3/ja/docs/ja/api/java/io/DataOutputStream.html
any ideas??
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thanks objects an CEHJ
Decided to go with the DataOuputStream method, It is a lot more efficient
Thanks for the lesson!
Decided to go with the DataOuputStream method, It is a lot more efficient
Thanks for the lesson!
>>Decided to go with the DataOuputStream method, It is a lot more efficient
I agree. And objects is right about the toByteArray method of BigInteger: if there are leading zeros in the long, they won't be represented by empty array elements - they'll simply be omitted. There really should be a toLongByteArray method or something returning all 8 bytes.
I agree. And objects is right about the toByteArray method of BigInteger: if there are leading zeros in the long, they won't be represented by empty array elements - they'll simply be omitted. There really should be a toLongByteArray method or something returning all 8 bytes.
BigInteger big = new BigInteger.valueOf(fileLen
testlong = big.toByteArray();
System.out.println(big.lo
//Copy to the packet
System.arraycopy(testlong