<i18n dev> java.util.Fomatter precision and surrogate pairs

Naoto Sato naoto.sato at oracle.com
Fri Feb 12 23:40:48 UTC 2021

Hi Jason,

On 2/12/21 9:24 AM, Jason Mehrens wrote:
> Hello i18n-dev,
> In the documentation for java.util.Formatter, precision is allowed for 's' general conversions but not 'c' conversions.  What is the rationale for this requirement?

Although the error message may be confusing, 'c' conversion cannot be 
used for a String argument (like in your example). It simply converts 
numeric value into a single character, thus no need for output 
"precision." I am not the designer of the class, so might be wrong.

> When using surrogate pairs the general conversion will tear surrogate pairs, which seems correct given the type of conversion.
> However, if you want to limit the precision and not tear surrogate pairs there no out of the box way to do this.
> My understanding is that you have to implement a Formattable which is not ideal.
> Reading the docs it looks like 'c' deals with Unicode but doesn't allow setting a precision (substring).
> Would it make sense to allow precision for character conversions and enforce a precision limit based on the code point count and not the length?
> I think it would be helpful for java.util.logging.SimpleFormatter and alike where a user wants to limit the max line size but not see garbage characters in the logs.

I cannot think of any good solutions off the top of my head, other than 
customizing your own.


> Thanks,
> Jason
> ====
> public class FormatterTester {
> 	public static void main(String[] args) {
> 		String nb = "\ud83c\udf09\ud83c\udf09";
> 		//'s', 'S'	general	If arg implements Formattable,
> 		///then arg.formatTo is invoked.
> 		//Otherwise, the result is obtained by invoking arg.toString().
> 		println("s", nb);
> 		//'c', 'C'|character|The result is a Unicode character
> 		//For general argument types, the precision is the
> 		//maximum number of characters to be written to the output.
> 		//... if a precision is provided, an exception will be thrown.
> 		println("c", nb);
> 	}
> 	private static void println(String conversion, String arg) {
> 		System.err.println("len=" + arg.length()
> 			+ " count=" + arg.codePointCount(0, arg.length()));
> 		for (int i = 1, p = arg.length() + 4; i < p; ++i) {
> 			try {
> 				System.err.println(String.format("%1$."+ i + conversion, arg));
> 			} catch (IllegalArgumentException iae) {
> 				System.err.println("p=" + i + ' ' + iae);
> 			}
> 		}
> 	}
> }
> ====

More information about the i18n-dev mailing list