What's the best way to convert an arbitrary Java String to a limited set of characters and back again?

I would like to generate an ETag from an arbitrary Java String, and then be able to reproduce the original String when that ETag is subsequently presented.

[RFC 7232](https://www.rfc-editor.org/rfc/rfc7232#section-2.3) and [RFC 7230](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6) between them define the valid characters as:

```
etagc          = %x21 / %x23-7E / obs-text
               ; VCHAR except double quotes, plus obs-text
obs-text       = %x80-FF

```

Loosely, that means any 8 bit character greater than or equal to `0x21`, except `0x22` and `0x7f`. Given that Java Strings can contain any Unicode character, there are quite a few that aren't permissible in an ETag.

Simplistically, because 0 - 9 and A - F are all valid ETag characters, I could:

1. convert the String to a UTF-8 byte array;
2. then convert each byte to a two-digit hex number;
3. then concatenate the hex numbers to make the ETag.

The code to reverse this is a little painful, but it *is* perfectly reversible, and it works for all Java Strings.

However, my simplistic method produces very long ETags, which is inefficient, and might cause problems in practice.

How can I produce shorter ETags by making use of the fact that there are 220 characters available to me? Is there a library for this very purpose?