Java Forum / First Aid / March 2008
Long integer to bytes?
nooneinparticular314159@yahoo.com - 04 Mar 2008 03:28 GMT I have a value that is represented as a 32 bit unsigned integer. Java, from what I understand, does not handle unsigned integers, but can represent the same number as a Long. I need to turn this Long into a 4 byte array representing the value of the 32 bit integer (which is really a long). Every method I've found so far seems to operate on single byte integers, not 4 byte integers (ie. longs). How can I get my value into a 4 byte array?
Thanks!
nooneinparticular314159@yahoo.com - 04 Mar 2008 03:32 GMT To follow up on that, here is an example:
Long PieceIndexNumber; byte PieceIndexBytes = PieceIndexNumber.byteValue();
Note that I can represent the byte value of PieceIndexNumber as a byte. Not four bytes. Just one. That doesn't make sense, since a long requires 4 bytes. What am I doing wrong here?
Thanks!
Eric Sosman - 04 Mar 2008 04:09 GMT > To follow up on that, here is an example: > [quoted text clipped - 4 lines] > byte. Not four bytes. Just one. That doesn't make sense, since a > long requires 4 bytes. What am I doing wrong here? Throwing away information. (Also, confusing four with eight.) Try this and see what you get:
Long l1 = new Long(1); byte b1 = l1.byteValue(); Long l2 = new Long(258); byte b2 = l2.byteValue(); Long l3 = new Long(65539); byte b3 = l3.byteValue(); Long l4 = new Long(16777220); b4 = l4.byteValue(); System.out.println(b1 + " " + b2 + " " + b3 + " " + b4);
Try to predict the output before you actually run the code.
 Signature Eric Sosman esosman@ieee-dot-org.invalid
nooneinparticular314159@yahoo.com - 04 Mar 2008 04:20 GMT > Throwing away information. (Also, confusing four with eight.) > Try this and see what you get: [quoted text clipped - 8 lines] > b4 = l4.byteValue(); > System.out.println(b1 + " " + b2 + " " + b3 + " " + b4); Ok. It looks like you are overflowing (slightly) various representations of a number by 1,2,3 and 4 by placing information into the bytes too large to fit into individual bytes. But how can I represent my number as bytes? (An array of bytes would be fine, if I knew how to get it into one.)
Thanks!
nooneinparticular314159@yahoo.com - 04 Mar 2008 08:39 GMT On Mar 3, 8:20 pm, "nooneinparticular314...@yahoo.com" <nooneinparticular314...@yahoo.com> wrote:
> > Throwing away information. (Also, confusing four with eight.) > > Try this and see what you get: [quoted text clipped - 8 lines] > > b4 = l4.byteValue(); > > System.out.println(b1 + " " + b2 + " " + b3 + " " + b4); Ok. I sort of see what you mean here. A long is 8 bytes. A 32 bit unsigned int is 4 bytes. I've tried using an 8 byte bytebuffer, but that represented a signed value and gave me negative numbers if I tried to store the wrong number. How can I store and extract a 32 bit unsigned int?
Thanks!
Nik.Ivanov - 04 Mar 2008 09:08 GMT May be you need something like: public byte[] pack(long value){ long tmp = value; int size = 0; do{ size ++; tmp <<= Byte.SIZE - 1; }while (tmp != 0); byte[] bytes = new byte[size]; for ( int i = 0; i < bytes.length ; i++){ tmp = value; for ( int j = 0 ;j < i ; j++){ tmp >>= Byte.SIZE - 1; } bytes[i] = (byte)(tmp & Byte.MAX_VALUE); } return bytes; } I belive that an unpack method is pretty clear, then you have packing;
Nik.Ivanov - 04 Mar 2008 09:16 GMT > do{ > size ++; > tmp <<= Byte.SIZE - 1; > }while (tmp != 0); Whoops, made a very simple mistake, it should be tmp >>= Byte.SIZE - 1, instead of tmp <<= Byte.SIZE - 1;
Roedy Green - 04 Mar 2008 12:08 GMT On Mon, 3 Mar 2008 19:28:14 -0800 (PST), "nooneinparticular314159@yahoo.com" <nooneinparticular314159@yahoo.com> wrote, quoted or indirectly quoted someone who said :
>I have a value that is represented as a 32 bit unsigned integer. >Java, from what I understand, does not handle unsigned integers, but [quoted text clipped - 3 lines] >operate on single byte integers, not 4 byte integers (ie. longs). How >can I get my value into a 4 byte array? see http://mindprod.com/jgloss/unsigned.html
long in java is 8 bytes, 64 bits. int in java is 4 bytes, 32 bits.
See http://mindprod.com/jgloss/primitive.html --
Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
rossum - 04 Mar 2008 13:19 GMT On Mon, 3 Mar 2008 19:28:14 -0800 (PST), "nooneinparticular314159@yahoo.com"
>I have a value that is represented as a 32 bit unsigned integer. >Java, from what I understand, does not handle unsigned integers, but [quoted text clipped - 5 lines] > >Thanks! I assume that you read in the initial value as a Java long rather than a Java integer.
To convert a long to a byte array I use the java.nio library. This assumes that all values are big-endian; I do not know if this will be a problem for you.
Code fragment:
import java.nio.LongBuffer; import java.nio.ByteBuffer;
private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
public byte[] longToBytes(long inLong) { byte[] bArray = new byte[BYTES_PER_LONG]; ByteBuffer bBuffer = ByteBuffer.wrap(bArray); LongBuffer lBuffer = bBuffer.asLongBuffer(); lBuffer.put(inLong); return bArray; }
This returns an 8-byte array, you just need the relevant four bytes of it.
rossum
nooneinparticular314159@yahoo.com - 04 Mar 2008 17:39 GMT Ok. I think I almost have it - sort of. Using the BigInteger class, I can actually store the value I need, and I can also get the last four bytes out of it. The problem is that the protocol that I'm using requires a 32 bit unsigned integer. So I can create a 32 bit unsigned int, say 4294967295 (2^32 -1), which takes four bytes to represent. I then stick an extra byte in front of it containing 0x00, and BigInteger correctly stores 4294967295. (If I don't do this, it stores -1.) The problem now is that I need to send this data over the network to other hosts, which may not be doing the BigInteger trick, and which absolutely expect a 32 bit number. I can't put the leading 0 in front, and I clearly don't want to send them -1. Is there a way around this, or am I just trying to use numbers that are too big to represent this way?
Thanks!
rossum - 04 Mar 2008 19:12 GMT On Tue, 4 Mar 2008 09:39:39 -0800 (PST), "nooneinparticular314159@yahoo.com"
>Ok. I think I almost have it - sort of. Using the BigInteger class, >I can actually store the value I need, and I can also get the last [quoted text clipped - 11 lines] > >Thanks! A few points:
BigIntegers are slow, ints or longs will be faster if speed is a problem for you.
How much control do you have over the protocol used to send to other hosts? BigInteger is serializable, as are Integer and Long - perhaps using a serialized Integer, Long or BigInteger might be better for your purposes.
Once you have the four byte array you could just send the four bytes in series. You would need to agree the endianness before making the change.
You could sent the 32 bit signed integer and expect the receiving end to convert -1 back to 4294967295.
I suspect you are going to have to talk to whoever is building the other end and come to some agreement as to how you are going to work this.
Basically you are trying to use numbers that are too big to represent in 31 bits (the positive part of the integer range). To use the full 32 bits someone is going to have to deal with negative numbers - your 4294967295 = -1 problem. On the positive side, both of these have exactly the same bit pattern representation so your problem is more one of translation than a more fundamental difficulty.
For myself I would probably go for a serialized signed Integer, but I do not know the full details of your problem.
rossum
nooneinparticular314159@yahoo.com - 05 Mar 2008 02:37 GMT > On Tue, 4 Mar 2008 09:39:39 -0800 (PST), > "nooneinparticular314...@yahoo.com" [quoted text clipped - 48 lines] > > rossum I'm attempting to implement a well defined protocol which has been widely implemented. I can't alter the protocol if I want to interoperate with existing implementations.
What I have gotten working is the use of BigIntegers internally within my program, but then I convert the last four bytes to a ByteArray, which means that I can send them over the network to other hosts running other implementations.
Nigel Wade - 05 Mar 2008 09:52 GMT > I'm attempting to implement a well defined protocol which has been > widely implemented. I can't alter the protocol if I want to [quoted text clipped - 4 lines] > which means that I can send them over the network to other hosts > running other implementations. Just use a DataOutputStream.
The unsigned arithmetic can be performed using longs. When you are ready to output the data you mask the low order 4 bytes into an int. Then write the int directly to the network using DataOutputStream.writeInt(). Java I/O is all network byte order (big endian) so there's no need to worry about byte swapping.
The following code will write the unsigned value 0xfedcba01 to a file:
package tests;
import java.io.DataOutputStream; import java.io.FileOutputStream;
public class IntOutput { public static void main(String[] args) { // create a 32bit, "unsigned" integer. long l = 0xfedcba01L; // mask off the 32bit low order bits into an int. int i = (int) l & 0xffffffff; System.out.println(l); System.out.println(i); try { // open a DataOutputStream, in this case to a file, but it could // just as easily be network connection. FileOutputStream fos = new FileOutputStream("tmp.tmp"); DataOutputStream dos = new DataOutputStream(fos); dos.writeInt(i); dos.close(); fos.close(); } catch(Exception e) { System.err.println(e); } } }
When you run it the output is: 4275878401 -19088895
The contents of the output file, when viewed using od are:
$ od -t x4 tmp.tmp 0000000 fedcba01 HEX $ od -D tmp.tmp 0000000 4275878401 Unsigned int $ od -t d4 tmp.tmp 0000000 -0019088895 Signed int
 Signature Nigel Wade, System Administrator, Space Plasma Physics Group, University of Leicester, Leicester, LE1 7RH, UK E-mail : nmw@ion.le.ac.uk Phone : +44 (0)116 2523548, Fax : +44 (0)116 2523555
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|