Reputation: 3213
How do I convert a long
to a byte[]
and back in Java?
I'm trying convert a long
to a byte[]
so that I will be able to send the byte[]
over a TCP connection. On the other side I want to take that byte[]
and convert it back into a double
.
Upvotes: 223
Views: 298133
Reputation: 191
I find this method to be most friendly.
byte[] b = BigInteger.valueOf(x).toByteArray();
long l = new BigInteger(b).longValue();
Upvotes: 19
Reputation: 1
public static long ToInt64(byte[] buffer) throws OutOfRangeException {
if (buffer.length < 8) {
throw new OutOfRangeException();
}
long int64 = 0;
int64 = buffer[0] & 0xffL;
int64 |= ((long) buffer[1] << 8) & 0xff00L;
int64 |= ((long) buffer[2] << 16) & 0xff0000L;
int64 |= ((long) buffer[3] << 24) & 0xff000000L;
int64 |= ((long) buffer[4] << 32) & 0xff00000000L;
int64 |= ((long) buffer[5] << 40) & 0xff0000000000L;
int64 |= ((long) buffer[6] << 48) & 0xff000000000000L;
int64 |= ((long) buffer[7] << 56);
return int64;
}
Upvotes: 0
Reputation: 6780
new ObjectMapper().writeValueAsString(1234L).getBytes(); //*
Clearly this is not the ideal solution in terms of bytes, but it's what everybody seems to do these days. Given op wants to convert it back to a double at the other end precision is probably not a concern.
(* if its not clear, this says: send it over TCP as JSON)
Upvotes: -1
Reputation: 581
All of the current answers are more complicated than they need to be and I’d hate for anyone locating this thread to walk away without a more concise option.
You can do both of these conversions in a single line.
byte[] to long:
ByteBuffer.wrap(yourBytes).getLong();
long to byte[]:
ByteBuffer.wrap(new byte[8]).putLong(yourLong).array();
Upvotes: 20
Reputation: 7
static byte[] longToBytes(Long l) {
return (l + "").getBytes(StandardCharsets.UTF_8);
}
Upvotes: -3
Reputation: 630
From Java 9, the best approach is to use VarHandle
, which will read from the byte array as if it is a long array, for performance make the VarHandle
instance a static final field.
static final VarHandle HANDLE = MethodHandles.byteArrayViewVarHandle(Long.TYPE.arrayType(), ByteOrder.nativeOrder());
static long bytesToLong(byte[] bytes, int offset) {
return (long)HANDLE.get(bytes, offset);
}
static void longToBytes(byte[] bytes, int offset, long value) {
HANDLE.set(bytes, offset, value);
}
Upvotes: 1
Reputation: 1565
I tested the ByteBuffer method against plain bitwise operations but the latter is significantly faster.
public static byte[] longToBytes(long l) {
byte[] result = new byte[8];
for (int i = 7; i >= 0; i--) {
result[i] = (byte)(l & 0xFF);
l >>= 8;
}
return result;
}
public static long bytesToLong(final byte[] b) {
long result = 0;
for (int i = 0; i < 8; i++) {
result <<= 8;
result |= (b[i] & 0xFF);
}
return result;
}
For Java 8+ we can use the static variables that were added:
public static byte[] longToBytes(long l) {
byte[] result = new byte[Long.BYTES];
for (int i = Long.BYTES - 1; i >= 0; i--) {
result[i] = (byte)(l & 0xFF);
l >>= Byte.SIZE;
}
return result;
}
public static long bytesToLong(final byte[] b) {
long result = 0;
for (int i = 0; i < Long.BYTES; i++) {
result <<= Byte.SIZE;
result |= (b[i] & 0xFF);
}
return result;
}
Upvotes: 107
Reputation: 2427
Kotlin extensions for Long and ByteArray types:
fun Long.toByteArray() = numberToByteArray(Long.SIZE_BYTES) { putLong(this@toByteArray) }
private inline fun numberToByteArray(size: Int, bufferFun: ByteBuffer.() -> ByteBuffer): ByteArray =
ByteBuffer.allocate(size).bufferFun().array()
@Throws(NumberFormatException::class)
fun ByteArray.toLong(): Long = toNumeric(Long.SIZE_BYTES) { long }
@Throws(NumberFormatException::class)
private inline fun <reified T: Number> ByteArray.toNumeric(size: Int, bufferFun: ByteBuffer.() -> T): T {
if (this.size != size) throw NumberFormatException("${T::class.java.simpleName} value must contains $size bytes")
return ByteBuffer.wrap(this).bufferFun()
}
You can see full code in my library https://github.com/ArtemBotnev/low-level-extensions
Upvotes: 2
Reputation: 31221
Here's another way to convert byte[]
to long
using Java 8 or newer:
private static int bytesToInt(final byte[] bytes, final int offset) {
assert offset + Integer.BYTES <= bytes.length;
return (bytes[offset + Integer.BYTES - 1] & 0xFF) |
(bytes[offset + Integer.BYTES - 2] & 0xFF) << Byte.SIZE |
(bytes[offset + Integer.BYTES - 3] & 0xFF) << Byte.SIZE * 2 |
(bytes[offset + Integer.BYTES - 4] & 0xFF) << Byte.SIZE * 3;
}
private static long bytesToLong(final byte[] bytes, final int offset) {
return toUnsignedLong(bytesToInt(bytes, offset)) << Integer.SIZE |
toUnsignedLong(bytesToInt(bytes, offset + Integer.BYTES));
}
Converting a long
can be expressed as the high- and low-order bits of two integer values subject to a bitwise-OR. Note that the toUnsignedLong
is from the Integer
class and the first call to toUnsignedLong
may be superfluous.
The opposite conversion can be unrolled as well, as others have mentioned.
Upvotes: 0
Reputation: 7952
If you are looking for a fast unrolled version, this should do the trick, assuming a byte array called "b" with a length of 8:
byte[] -> long
long l = ((long) b[7] << 56)
| ((long) b[6] & 0xff) << 48
| ((long) b[5] & 0xff) << 40
| ((long) b[4] & 0xff) << 32
| ((long) b[3] & 0xff) << 24
| ((long) b[2] & 0xff) << 16
| ((long) b[1] & 0xff) << 8
| ((long) b[0] & 0xff);
long -> byte[] as an exact counterpart to the above
byte[] b = new byte[] {
(byte) lng,
(byte) (lng >> 8),
(byte) (lng >> 16),
(byte) (lng >> 24),
(byte) (lng >> 32),
(byte) (lng >> 40),
(byte) (lng >> 48),
(byte) (lng >> 56)};
Upvotes: 48
Reputation: 27926
public byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.putLong(x);
return buffer.array();
}
public long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.put(bytes);
buffer.flip();//need flip
return buffer.getLong();
}
Or wrapped in a class to avoid repeatedly creating ByteBuffers:
public class ByteUtils {
private static ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
public static byte[] longToBytes(long x) {
buffer.putLong(0, x);
return buffer.array();
}
public static long bytesToLong(byte[] bytes) {
buffer.put(bytes, 0, bytes.length);
buffer.flip();//need flip
return buffer.getLong();
}
}
Since this is getting so popular, I just want to mention that I think you're better off using a library like Guava in the vast majority of cases. And if you have some strange opposition to libraries, you should probably consider this answer first for native java solutions. I think the main thing my answer really has going for it is that you don't have to worry about the endian-ness of the system yourself.
Upvotes: 294
Reputation: 533920
Why do you need the byte[]? why not just write it to the socket?
I assume you mean long rather than Long, the latter needs to allow for null values.
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
dos.writeLong(longValue);
DataInputStream dis = new DataInputStream(
new BufferedInputStream(socket.getInputStream()));
long longValue = dis.readLong();
Upvotes: 16
Reputation: 11457
You could use the Byte conversion methods from Google Guava.
Example:
byte[] bytes = Longs.toByteArray(12345L);
Upvotes: 115
Reputation: 12444
I will add another answer which is the fastest one possible ׂ(yes, even more than the accepted answer), BUT it will not work for every single case. HOWEVER, it WILL work for every conceivable scenario:
You can simply use String as intermediate. Note, this WILL give you the correct result even though it seems like using String might yield the wrong results AS LONG AS YOU KNOW YOU'RE WORKING WITH "NORMAL" STRINGS. This is a method to increase effectiveness and make the code simpler which in return must use some assumptions on the data strings it operates on.
Con of using this method: If you're working with some ASCII characters like these symbols in the beginning of the ASCII table, the following lines might fail, but let's face it - you probably will never use them anyway.
Pro of using this method: Remember that most people usually work with some normal strings without any unusual characters and then the method is the simplest and fastest way to go.
from Long to byte[]:
byte[] arr = String.valueOf(longVar).getBytes();
from byte[] to Long:
long longVar = Long.valueOf(new String(byteArr)).longValue();
Upvotes: 2
Reputation: 6039
You could use the implementation in org.apache.hadoop.hbase.util.Bytes http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html
The source code is here:
Look for the toLong and toBytes methods.
I believe the software license allows you to take parts of the code and use it but please verify that.
Upvotes: 5
Reputation: 601
public static long bytesToLong(byte[] bytes) {
if (bytes.length > 8) {
throw new IllegalMethodParameterException("byte should not be more than 8 bytes");
}
long r = 0;
for (int i = 0; i < bytes.length; i++) {
r = r << 8;
r += bytes[i];
}
return r;
}
public static byte[] longToBytes(long l) {
ArrayList<Byte> bytes = new ArrayList<Byte>();
while (l != 0) {
bytes.add((byte) (l % (0xff + 1)));
l = l >> 8;
}
byte[] bytesp = new byte[bytes.size()];
for (int i = bytes.size() - 1, j = 0; i >= 0; i--, j++) {
bytesp[j] = bytes.get(i);
}
return bytesp;
}
Upvotes: 3
Reputation: 5499
Just write the long to a DataOutputStream with an underlying ByteArrayOutputStream. From the ByteArrayOutputStream you can get the byte-array via toByteArray():
class Main
{
public static byte[] long2byte(long l) throws IOException
{
ByteArrayOutputStream baos=new ByteArrayOutputStream(Long.SIZE/8);
DataOutputStream dos=new DataOutputStream(baos);
dos.writeLong(l);
byte[] result=baos.toByteArray();
dos.close();
return result;
}
public static long byte2long(byte[] b) throws IOException
{
ByteArrayInputStream baos=new ByteArrayInputStream(b);
DataInputStream dos=new DataInputStream(baos);
long result=dos.readLong();
dos.close();
return result;
}
public static void main (String[] args) throws java.lang.Exception
{
long l=123456L;
byte[] b=long2byte(l);
System.out.println(l+": "+byte2long(b));
}
}
Works for other primitives accordingly.
Hint: For TCP you do not need the byte[] manually. You will use a Socket socket
and its streams
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..
instead.
Upvotes: 4
Reputation: 33582
If you are already using an OutputStream
to write to the socket, then DataOutputStream might be a good fit. Here is an example:
// Assumes you are currently working with a SocketOutputStream.
SocketOutputStream outputStream = ...
long longValue = ...
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeLong(longValue);
dataOutputStream.flush();
There are similar methods for short
, int
, float
, etc. You can then use DataInputStream on the receiving side.
Upvotes: 0