22

What is the recommended way to handle an UnsupportedEncodingException when calling String.getBytes("UTF-8") inside a library method?

If I'm reading http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html correctly, UTF-8 encoding should always be available, which leads me to believe there's no reason to pass this exception on to the library's consumer (that is, add a throws clause to the method signature). It seems any failure mode that made UTF-8 encoding facilities unavailable would be catastrophic, leading me to write this handler:

    try
    {
        ....
        return "blah".getBytes("UTF-8");
    }
    catch (UnsupportedEncodingException e)
    {
        // we're assuming UTF-8 encoding is always available.
        // see
        // http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
        e.printStackTrace();
        return null; //prevent compile-time "method must return a result" errors
    }

Is there a failure mode that wouldn't be addressed by this snippet?

1
  • This question is not a duplicate as the question it's supposed to be a duplicate of involves URL encoding/decoding. I vote to reopen. Commented Sep 22, 2014 at 20:20

3 Answers 3

56

You know what I do?

return "blah".getBytes( Charset.forName( "UTF-8" ) );

This one doesn't throw a checked exception.

Update: Since Java 1.7, we have StandardCharsets.

return "blah".getBytes( StandardCharsets.UTF_8 );
Sign up to request clarification or add additional context in comments.

2 Comments

+1 for avoiding the problem altogether. :) Marking this as an answer doesn't seem completely correct, though...
This seems like the best solution. Charset.forName throws an unchecked exception, which is what UnsupportedEncodingException should have been to begin with.
3

I ran across this question while trying to figure out if UTF-8 is always available. So thanks for the link.

I agree that there is no need to throw a checked exception when it comes to encoding and decoding using a specific character set that is guaranteed to be available. If the character set was a variable that was passed in, I would probably throw UnsupportedEncodingException.

This is what I am doing in a similar piece of Android code:

public static String encode(String input) {
    try {
        return URLEncoder.encode(input, CharEncoding.UTF_8);
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
    }
}

CharEncoding.UTF_8 is just Apache Commons' String constant for "UTF-8".

Judge Mental's suggestion to use StandardCharsets.UTF_8 is great but for those of us doing Android development, it's only available on SDK 19 (KitKat) and above.

1 Comment

If StandardCharsets is not available, there's nothing stopping you from writing your own MyStandardCharsets class with some public static final Charsets initialized using Charset.forName.
1

If you use Lombok, @SneakyThrows annotation can be used to avoid this.

From Lombok documentation:

"@SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's throws clause.

  • An 'impossible' exception. For example, new String(someByteArray, "UTF-8"); declares that it can throw an UnsupportedEncodingException but according to the JVM specification, UTF-8 must always be available. An UnsupportedEncodingException here is about as likely as a ClassNotFoundError when you use a String object, and you don't catch those either! "

https://projectlombok.org/features/SneakyThrows

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.