Home > Archive > Java Help > March 2008 > Long integer to bytes?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Long integer to bytes?
|
|
| nooneinparticular314159@yahoo.com 2008-03-03, 10:29 pm |
| 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 2008-03-03, 10:29 pm |
| 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 2008-03-03, 10:29 pm |
| nooneinparticular314159@yahoo.com wrote:
> 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?
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.
--
Eric Sosman
esosman@ieee-dot-org.invalid
| |
| nooneinparticular314159@yahoo.com 2008-03-03, 10:29 pm |
| > =A0 =A0 =A0Throwing away information. =A0(Also, confusing four with eight.=
)
> Try this and see what you get:
>
> =A0 =A0 =A0 =A0 Long l1 =3D new Long(1);
> =A0 =A0 =A0 =A0 byte b1 =3D l1.byteValue();
> =A0 =A0 =A0 =A0 Long l2 =3D new Long(258);
> =A0 =A0 =A0 =A0 byte b2 =3D l2.byteValue();
> =A0 =A0 =A0 =A0 Long l3 =3D new Long(65539);
> =A0 =A0 =A0 =A0 byte b3 =3D l3.byteValue();
> =A0 =A0 =A0 =A0 Long l4 =3D new Long(16777220);
> =A0 =A0 =A0 =A0 b4 =3D l4.byteValue();
> =A0 =A0 =A0 =A0 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 2008-03-04, 4:22 am |
| On Mar 3, 8:20=A0pm, "nooneinparticular314...@yahoo.com"
<nooneinparticular314...@yahoo.com> wrote:
t.)[color=darkred]
>
[color=darkred]
>
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 2008-03-04, 4:22 am |
|
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 2008-03-04, 4:22 am |
| On Mar 4, 12:08 pm, "Nik.Ivanov" <Nik.Iva...@gmail.com> wrote:
> 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 2008-03-04, 8:21 am |
| 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
>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?
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 2008-03-04, 8:21 am |
| On Mon, 3 Mar 2008 19:28:14 -0800 (PST),
"nooneinparticular314159@yahoo.com"
<nooneinparticular314159@yahoo.com> wrote:
>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!
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 2008-03-04, 7:26 pm |
| 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 2008-03-04, 7:26 pm |
| On Tue, 4 Mar 2008 09:39:39 -0800 (PST),
"nooneinparticular314159@yahoo.com"
<nooneinparticular314159@yahoo.com> wrote:
>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!
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 2008-03-04, 10:25 pm |
| On Mar 4, 11:12=A0am, rossum <rossu...@coldmail.com> wrote:
> On Tue, 4 Mar 2008 09:39:39 -0800 (PST),
> "nooneinparticular314...@yahoo.com"
>
>
>
> <nooneinparticular314...@yahoo.com> wrote:
[color=darkred]
>
>
> 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? =A0BigInteger 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. =A0You 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). =A0To use the full
> 32 bits someone is going to have to deal with negative numbers - your
> 4294967295 =3D -1 problem. =A0On 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
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 2008-03-05, 4:35 am |
| nooneinparticular314159@yahoo.com wrote:
>
> 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.
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
--
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
|
|
|
|
|