5

What is the most time efficient way to create and Base32 encode a random UUID in Java? I would like to use Base32 encoding to store globally unique IDs that are usable in URLs.

8
  • 1
    I imagine he wants to condense the characters needed to express a UUID for an HTTP GET. There is a non-trivial limit on the length of an HTTP GET after all. I don't see anything wrong with this question at all. Commented Jan 13, 2014 at 23:46
  • 1
    @GlennLane Both Base64 and Base32 would increase the size of the UUID, and since it's already a hex string (with dashes) there's no issues with using it in urls re: encoding. Hence "Why would you ever do that". Commented Jan 13, 2014 at 23:55
  • 1
    He's using them in a URL... so they are expressed as strings. Most people would use hex, but it's 32 characters. Using Base64 is 22 characters. Commented Jan 14, 2014 at 0:01
  • 1
    @BrianRoach I think I know the confusion here... he doesn't want to Base32 encode the 36-character UUID hex-string. He wants to encode the 16-byte binary. Commented Jan 14, 2014 at 1:29
  • That's right. If there isn't much overhead doing the encoding after generation, the space savings starts to get significant when it's over billions of nodes. Commented Jan 14, 2014 at 3:29

3 Answers 3

5

Base32 still pads with the = character, so you'll need to do something with that if you really want to avoid URL escaping.

If you really want to avoid Base16, I recommend you use Base64 instead of Base32. If you want to use an RFC standard, try base64url. However, that standard also uses "=" for the trailing padding, so you need to escape that. It's substitutions are:

  • + -> -
  • / -> _
  • = -> =

Personally, I use a variant called Y64. It's substitutions are:

  • + -> .
  • / -> _
  • = -> -

It's not an RFC standard, but at least you don't have to worry about escaping the trailing "=".

Apache Commons Codec provides both Base64 and Base32. Here's an example with Base64 with the Y64 variant

To encode:

UUID uuid = UUID.randomUUID(); ByteBuffer uuidBuffer = ByteBuffer.allocate(16); LongBuffer longBuffer = uuidBuffer.asLongBuffer(); longBuffer.put(uuid.getMostSignificantBits()); longBuffer.put(uuid.getLeastSignificantBits()); String encoded = new String(Base64.encode(uuidBuffer.array()), Charset.forName("US-ASCII")); encoded = encoded.replace('+', '.') .replace('/', '_') .replace('=', '-'); 

And decode:

String encoded; // from your request parameters or whatever encoded = encoded.replace('.', '+') .replace('_', '/') .replace('-', '='); ByteBuffer uuidBuffer = ByteBuffer.wrap(Base64.decode( encoded.getBytes(Charset.forName("US-ASCII")))); LongBuffer longBuffer = uuidBuffer.asLongBuffer(); UUID uuid = new UUID(longBuffer.get(), longBuffer.get()); 
Sign up to request clarification or add additional context in comments.

1 Comment

problem is Uppercase Lowercase output string, when using a case-insensitive filesystem
1

I agreed with the discussion that Base64Url might be more suitable but I also see the benefit of generating unique value in Base32. It's case insensitive that is easier to handle if human is involved.

This is my code to convert UUID to Base32 using Guava's BaseEncoding.

 public static String toBase32(UUID uuid){ ByteBuffer bb = ByteBuffer.wrap(new byte[16]); bb.putLong(uuid.getMostSignificantBits()); bb.putLong(uuid.getLeastSignificantBits()); return BaseEncoding.base32().omitPadding().encode(bb.array()); } 

Comments

1

The codec Base32Codec can encode UUIDs efficiently to base-32.

// Returns a base-32 string // uuid::: 01234567-89AB-4DEF-A123-456789ABCDEF // base32: aerukz4jvng67ijdivtytk6n54 String string = Base32Codec.INSTANCE.encode(uuid); 

There are codecs for other encodings in the same package of uuid-creator.


Disclaimer: I'm the main contributor of uuid-creator.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.