How do I convert Long to byte[] and back in java

244,778

Solution 1

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.

Solution 2

You could use the Byte conversion methods from Google Guava.

Example:

byte[] bytes = Longs.toByteArray(12345L);

Solution 3

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;
}

Solution 4

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)};

Solution 5

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();
Share:
244,778

Related videos on Youtube

Emre801
Author by

Emre801

Updated on April 23, 2022

Comments

  • Emre801
    Emre801 about 2 years

    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.

  • Stephen C
    Stephen C over 13 years
    Clever ... but you create and discard a temporary ByteBuffer for each conversion. Not good if you are sending multiple longs per message and/or lots of messages.
  • Brad Mace
    Brad Mace over 13 years
    @Stephen - I was just doing enough to demonstrate how to use ByteBuffer, but I went ahead and added an example of using it in a utility class.
  • Alex Miller
    Alex Miller over 12 years
    I think the bytesToLong() here would fail as the position after the put is at the end of the buffer, not the beginning. I think you'd get a buffer underflow exception.
  • nullptr
    nullptr over 11 years
    @BradMace, can you please edit your answer, this answer is wrong per Alex Miller, and using your method [static long bytesToLong(bytes)] I run into troubles.. You should have put bytes in proper location or you should clear buffer. I was getting BufferOverflowException.
  • user1132959
    user1132959 almost 11 years
    He asked how you convert to byte[] and back. Good answer but didn't answer the question. You ask why because you assume it is unnecessary but that's a wrong assumption. What if he is doing cross-language or cross-platform? DataOutputStream won't help you there.
  • Ian McLaird
    Ian McLaird over 10 years
    If he's doing cross-language or cross-platform, then sending the bytes in a known order is important. This method does that (it writes them "high byte first") according to the docs. The accepted answer does not (it writes them in the "current order" according to the docs). The question states that he wants to send them over a TCP connection. The byte[] is just a means to that end.
  • jr.
    jr. over 10 years
    Great answer. It wasn't immediately clear to me why you need to "flip", but I stumbled upon this article which helped a lot! tutorials.jenkov.com/java-nio/buffers.html Perhaps flip is a misnomer?
  • Prashant
    Prashant over 10 years
    you can skip the ArrayList: public static byte[] longToBytes(long l) { long num = l; byte[] bytes = new byte[8]; for (int i = bytes.length - 1, i >= 0; i--) { bytes[i] = (byte)(num & 0xff); num >>= 8; } return bytesp; }
  • jvdbogae
    jvdbogae almost 10 years
    Pre-Java 8, you can use Long.SIZE/Byte.SIZE instead of Long.BYTES to avoid a magic number.
  • Aaron Zinman
    Aaron Zinman over 9 years
    The reuse of that bytebuffer is highly problematic, and not just for the thread-safety reasons as others commented. Not only would a '.clear()' be needed in between, but what's not obvious is that calling .array() on the ByteBuffer is returning the backing array versus a copy. Thus if you call repeatedly and hold onto the other results, they're actually all the same array that repeatedly is overwriting the previous values. The hadoop link in a comment below is the most performant and avoids any of these issues.
  • Vipul
    Vipul over 8 years
    Instead of result |= (b[i] & 0xFF); We could simply use result |= b[i]; as and with 0xFF for a bit doesnt modify anything.
  • Brainstorm
    Brainstorm over 8 years
    @Vipul The bitwise-and does matter because when doing just result |= b[i] the byte value will first be converted to long which does sign extension. A byte with value -128 (hex 0x80) will turn into a long with value -128 (hex 0xFFFF FFFF FFFF FF80). First after the conversion are the values or:ed together. Using bitwise-and protects against this by first converting the byte to an int and cutting off the sign extension: (byte)0x80 & 0xFF ==> (int)0xFFFF FF80 & 0xFF ==> (int) 0x80. Why bytes are signed in java is a bit of a mystery to me, but I guess that it's to fit in with other types.
  • Mahmoud Hanafy
    Mahmoud Hanafy about 8 years
    @Brainstorm I tried case -128 with |= b[i] and with |= (b[i] & 0xFF) and the results are the same !!
  • Wytze
    Wytze about 8 years
    The problem is that the byte gets promoted before the shift is applied which causes strange problems with the sign bit. Therefore we first and (&) it with 0xFF to get the correct value to shift.
  • David Phillips
    David Phillips almost 8 years
    @IanMcLaird The accepted answer does use a known order. It creates a new ByteBuffer which according to the docs "The initial order of a byte buffer is always BIG_ENDIAN.
  • Kirill Gamazkov
    Kirill Gamazkov about 7 years
    Sorry for necroposting, but that's just wrong. E. g. String.valueOf(0).getBytes()[0] == 0x30. Surprise! String#getBytes will return ASCII-encoded digit symbols, not digits: '0' != 0, but '0' == 0x30
  • Yonatan Nir
    Yonatan Nir about 7 years
    Well maybe if you had read my entire answer then you'd seen I have warned about it in the answer itself..
  • Kirill Gamazkov
    Kirill Gamazkov about 7 years
    Ah, I missed the point that intermediate byte[] data is treated as (almost) opaque. Your trick will do for this scenario.
  • jefry jacky
    jefry jacky over 6 years
    I try to convert this data (data = new byte[]{(byte) 0xDB, (byte) 0xA7, 0x53, (byte) 0xF8, (byte) 0xA8, 0x0C, 0x66, 0x8}; ) to long, but it return false value -2619032330856274424, the expected value is 989231983928329832
  • Wytze
    Wytze over 6 years
    The hexadecimal representation of 989231983928329832 is 0DBA753F8A80C668. The leading 0 probably fell of causing the conversion error.
  • victtim
    victtim over 5 years
    Why does that implementation use XOR (^=) instead of OR? github.com/apache/hbase/blob/master/hbase-common/src/main/ja‌​va/…
  • Big_Bad_E
    Big_Bad_E almost 5 years
    The original method doesn't work with negative numbers as it gets in an infinite loop in while (l != 0), @eckes's method doesn't work with numbers over 127 because he doesn't account for bytes going negative over 127 cause they are signed.
  • Miha_x64
    Miha_x64 almost 4 years
    Thank you, the best!
  • mjs
    mjs over 3 years
    this is the same as from google guava. at least the first. it should be safe.
  • Christian Hujer
    Christian Hujer over 3 years
    The left-shift by Long.BYTES is wrong. It does not communicate the intent. It only works by coincidece: Long.BYTES is 8. Replace this with Integer, and it will be wrong. Instead, left-shift by Byte.SIZE.
  • Wytze
    Wytze over 3 years
    My original answer was edited by someone. I have restored it as it was.
  • Snipe3000
    Snipe3000 about 3 years
    Anyone else only getting java.nio.BufferOverflowException issues?
  • dnault
    dnault almost 3 years
    This assumes little-endian byte order, and the long -> byte[] code added by someone else in a subsequent edit fails for negative numbers :-/
  • asgs
    asgs over 2 years
    the bytesToLong method can also do a return ByteBuffer.wrap(bytes).getLong()
  • Admin
    Admin over 2 years
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.