?
Solved

Sending A Long in a byte Array

Posted on 2003-11-11
19
Medium Priority
?
557 Views
Last Modified: 2010-03-31
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
0
Comment
Question by:welsh_boy
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 7
  • 3
19 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 9726216
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 9726226
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 9726253
LOL, and the second index should be 1, not 0 (just saw the thing about the header). Make sure testbuffer.length >= 9
0
Get real performance insights from real users

Key features:
- Total Pages Views and Load times
- Top Pages Viewed and Load Times
- Real Time Site Page Build Performance
- Users’ Browser and Platform Performance
- Geographic User Breakdown
- And more

 
LVL 92

Expert Comment

by:objects
ID: 9726294
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
 
LVL 92

Expert Comment

by:objects
ID: 9726307
Similiar techniques can also be used for going the other direction.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9726367
It's only slow if it's perceptibly slow - and it almost certainly won't be. It's certainly more elegant and clearer.
0
 
LVL 92

Expert Comment

by:objects
ID: 9726440
More elegant and clear than:

long l = in.readLong();

I don't think so :)
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9726459
I was talking about your first suggestion
0
 

Author Comment

by:welsh_boy
ID: 9726465
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
 
LVL 92

Expert Comment

by:objects
ID: 9726500
DataOuputStream out = new DataOutputStream(new ByteArrayOutputStream(128));
out.writeByte(PacketCode.SFT);
out.writeLong(fileLength);
out.write(tester);
byte [] testbuffer= out.toByteArray();
0
 
LVL 92

Expert Comment

by:objects
ID: 9726515
And reading it back:

DataInputStream in = new DataInputStream(new ByteArrayInputStream(testbuffer));
byte packet = in.readByte();
long fileLength = in.readLong();
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 200 total points
ID: 9726590
>>//<-- 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
 
LVL 92

Expert Comment

by:objects
ID: 9726691
> 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
 
LVL 92

Expert Comment

by:objects
ID: 9726708
Actually thats not right either, should be:

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

Lot simpler to use DataOutput :)
0
 

Author Comment

by:welsh_boy
ID: 9726710
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
 
LVL 92

Assisted Solution

by:objects
objects earned 800 total points
ID: 9726751
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
 

Author Comment

by:welsh_boy
ID: 9726809
thanks objects an CEHJ

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

Thanks for the lesson!
0
 
LVL 92

Expert Comment

by:objects
ID: 9726821
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9730507
>>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

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
Suggested Courses
Course of the Month10 days, 6 hours left to enroll

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question