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(fileLength));
     byte[] testlong = new byte[8];
     testlong =  big.toByteArray();
     String dickString = new String(testlong);
     System.out.println(big.longValue() );//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(testbuffer, 1, fileSize, 0, 8);
     BigInteger big2 = new BigInteger(fileSize);
     System.out.println(big2.longValue() );


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
welsh_boyAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
Try

BigInteger big = new BigInteger.valueOf(fileLength);
     testlong =  big.toByteArray();
     System.out.println(big.longValue() );//test to see if its seding the right value
     //Copy to the packet
     System.arraycopy(testlong, 0, testbuffer, 0, 8);
0
CEHJCommented:
Sorry:

     BigInteger big = new BigInteger.valueOf(fileLength);
     byte[] testlong =  big.toByteArray();
     System.out.println(big.longValue() );//test to see if its sending the right value
     //Copy to the packet
     System.arraycopy(testlong, 0, testbuffer, 0, 8);
0
CEHJCommented:
LOL, and the second index should be 1, not 0 (just saw the thing about the header). Make sure testbuffer.length >= 9
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

objectsCommented:
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();
0
objectsCommented:
Similiar techniques can also be used for going the other direction.
0
CEHJCommented:
It's only slow if it's perceptibly slow - and it almost certainly won't be. It's certainly more elegant and clearer.
0
objectsCommented:
More elegant and clear than:

long l = in.readLong();

I don't think so :)
0
CEHJCommented:
I was talking about your first suggestion
0
welsh_boyAuthor Commented:
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.SFT;
//Copy File name at byte[9]
      System.arraycopy(tester, 0, testbuffer, 9, tester.length);



     BigInteger big = new BigInteger(Long.toString(fileLength));
     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(testbuffer, 1, fileSize, 0, 8);
     BigInteger big2 = new BigInteger(fileSize);
     System.out.println("Read Long from Data Packet: " + big2.longValue() );
0
objectsCommented:
DataOuputStream out = new DataOutputStream(new ByteArrayOutputStream(128));
out.writeByte(PacketCode.SFT);
out.writeLong(fileLength);
out.write(tester);
byte [] testbuffer= out.toByteArray();
0
objectsCommented:
And reading it back:

DataInputStream in = new DataInputStream(new ByteArrayInputStream(testbuffer));
byte packet = in.readByte();
long fileLength = in.readLong();
0
CEHJCommented:
>>//<-- I get an out of bounds error here

Are you perhaps reassigning testbuffer to another array reference in the mean time?

Check the lengths of

testlong
testbuffer
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
objectsCommented:
> 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);
0
objectsCommented:
Actually thats not right either, should be:

System.arraycopy(testlong, 0, testbuffer, 1+(8-testlong.length), testlong.length);

Lot simpler to use DataOutput :)
0
welsh_boyAuthor Commented:
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??
0
objectsCommented:
Oops, my fault. That methods on the underlying ByteArrayOutputStream.

ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
DataOuputStream out = new DataOutputStream(bout);
out.writeByte(PacketCode.SFT);
out.writeLong(fileLength);
out.write(tester);
byte [] testbuffer= bout.toByteArray();
0
welsh_boyAuthor Commented:
thanks objects an CEHJ

Decided to go with the DataOuputStream method, It is a lot more efficient

Thanks for the lesson!
0
objectsCommented:
0
CEHJCommented:
>>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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.