28

I just wrote this code to convert a GUID into a byte array. Can anyone shoot any holes in it or suggest something better?

 public static byte[] getGuidAsByteArray(){

 UUID uuid = UUID.randomUUID();
 long longOne = uuid.getMostSignificantBits();
 long longTwo = uuid.getLeastSignificantBits();

 return new byte[] {
      (byte)(longOne >>> 56),
      (byte)(longOne >>> 48),
      (byte)(longOne >>> 40),
      (byte)(longOne >>> 32),   
      (byte)(longOne >>> 24),
      (byte)(longOne >>> 16),
      (byte)(longOne >>> 8),
      (byte) longOne,
      (byte)(longTwo >>> 56),
      (byte)(longTwo >>> 48),
      (byte)(longTwo >>> 40),
      (byte)(longTwo >>> 32),   
      (byte)(longTwo >>> 24),
      (byte)(longTwo >>> 16),
      (byte)(longTwo >>> 8),
      (byte) longTwo
       };
}

In C++, I remember being able to do this, but I guess theres no way to do it in Java with the memory management and all?:

    UUID uuid = UUID.randomUUID();

    long[] longArray = new long[2];
    longArray[0] = uuid.getMostSignificantBits();
    longArray[1] = uuid.getLeastSignificantBits();

    byte[] byteArray = (byte[])longArray;
    return byteArray;

Edit

If you want to generate a completely random UUID as bytes that does not conform to any of the official types, this will work and wastes 10 fewer bits than type 4 UUIDs generated by UUID.randomUUID():

    public static byte[] getUuidAsBytes(){
    int size = 16;
    byte[] bytes = new byte[size];
    new Random().nextBytes(bytes);
    return bytes;
}
Chris Dutrow
  • 48,402
  • 65
  • 188
  • 258
  • Dupe - http://stackoverflow.com/questions/1055413 ? – Gishu Jun 06 '10 at 04:36
  • No, I was mentioning that in C++, you could have skipped having to copy everything into another array, but it doesn't look like you can do that in Java. – Chris Dutrow Jun 06 '10 at 04:46
  • possible duplicate of [Sending a Java UUID to C++ as bytes and back over TCP](http://stackoverflow.com/questions/1055413/sending-a-java-uuid-to-c-as-bytes-and-back-over-tcp) – finnw Jun 06 '10 at 09:21

4 Answers4

66

I would rely on built in functionality:

ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();

or something like,

ByteArrayOutputStream ba = new ByteArrayOutputStream(16);
DataOutputStream da = new DataOutputStream(ba);
da.writeLong(uuid.getMostSignificantBits());
da.writeLong(uuid.getLeastSignificantBits());
return ba.toByteArray();

(Note, untested code!)

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 1
    It does not give the same UUID when I call UUID.nameUUIDFromBytes(bb.array()); – Anon21 Jul 27 '13 at 01:47
  • 6
    @AlexandreH.Tremblay that's to be expected, nameUUIDFromBytes takes a hash from the bytes you pass to it. to deserialize the format above read the longs again and use the constructor UUID(long,long) – bcolyn Sep 24 '13 at 14:47
15
public static byte[] newUUID() {
    UUID uuid = UUID.randomUUID();
    long hi = uuid.getMostSignificantBits();
    long lo = uuid.getLeastSignificantBits();
    return ByteBuffer.allocate(16).putLong(hi).putLong(lo).array();
}
comonad
  • 5,134
  • 2
  • 33
  • 31
4

You can check UUID from apache-commons. You may not want to use it, but check the sources to see how its getRawBytes() method is implemented:

public UUID(long mostSignificant, long leastSignificant) {
    rawBytes = Bytes.append(Bytes.toBytes(mostSignificant), Bytes.toBytes(leastSignificant));
}
tne
  • 7,071
  • 2
  • 45
  • 68
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • sorry for commenting on old post. but why not use this : uuid.toString().getBytes() – MoienGK Feb 10 '15 at 09:24
  • and how you should convert the byte[] to mostSignificat and leastSignificatnt in order to regenerate the original uuid? – MoienGK Feb 10 '15 at 09:26
  • 1
    `uuid.toString().getBytes()` builds a byte[] containing the byte representation of the system's default string encoding of the textual representation of the UUID. So, probably the UTF-8 bytes that represent a string like `37B4C0FB-6BEB-4EEF-8D4F-5552C3C76952`. That's 36 bytes long. On the other hand, the proposed solution is just two `long`s, or 128 bits, or 16 bytes. So, 44% of the space. – Patrick Linskey Nov 23 '16 at 19:08
0

You could take a look at Apache Commons Lang3 Conversion.uuidToByteArray(...). Conversely, look at Conversion.byteArrayToUuid(...) to convert back to a UUID.