简体   繁体   中英

Android Java.Lang Locale Number Format I/O Asymmetry Problem

Historically the Android phones sold in South Africa provided English.US and English.UK locale support, but recently English.ZA (South Africa) has made an appearance, on Android 9.0 Samsung Galaxy A10, for example.

This particular Locale is showing asymmetric treatment of number formats, using the Locale.DE (German/Dutch) convention when converting Floats and Doubles into character strings[*1], but raising Java.Lang.NumberFormatException when reading back the self-same generated strings. For instance:

// on output
Float fltNum = 1.23456F;
System.out.println(String.format(Locale.getDefault(),"%f",fltNum)); // prints '1,23456'
// on Input
String fltStr = "1,23456";
Float fltVal;
fltVal = Float(fltStr); // generates NumberFormatException
fltVal = Float.parseFloat(fltStr); // also generates NumberFormatException
// Giving the compiler Float hints fltStr = "1,23456F" does not help
// Only fltStr = '1.23456' converts into a Float.

The temptation would be to swap decimal separators on reads, but that is the task of Float.parseFloat(), a not of the programer, for doing so shall again break other Locale.DE-likes, such as Locale.ID (Indonesia) which my App supports.

My additional question directed more at Locale arbitrators is: Does English.ZA not imply English conformant as would say German.NA (Namibia) be German conformant? One would think the natural designation for this particular number conversion would be Dutch.ZA (colloquially 'Afrikaans'), for Dutch conformance, but Android designates it as English.ZA?

NB (*1) This Android English.ZA conforms only partially as it does not produce either the German point group separator or the local clerical (pen-and-paper) space character group separator.

Apologies for using 'Answer' to respond to diogenesgg's comment suggestion:

"Hi, please take a look at this answer stackoverflow.com/questions/5233012/…. TL/DR."

In it I found a few gems - (1)

NumberFormat f = NumberFormat.getInstance(Locale.getDefault());
if (f instanceof DecimalFormat) {
    ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
}

But this is neutral and not value-specific so I added after the above,

(2) Given:

String axisValue("some-float-value-rendered as string");
NumberFormat nf = new DecimalFormat(axisValue);

Which I incorporate sequentially:

NumberFormat nf = new DecimalFormat(axisValue);
Number n;
if(nf instanceof DecimalFormat){
    try{
        n = nf.parse (axisValue);
        axisComponent = (Double) n;
    } catch (java.text.ParseException jtpe) {
    jtpe.printStackTrace();
    }
}

Notice the need to cast the Number n to Double.

This worked mostly under the problematic Locale English.ZA, until the value 0,00000 showed up.

For the string value "0,00000", NumberFormat decides Number n is a Long, and the system throws a (Long to Double) CastException.

I tried to trick NumberFormat in all ways I can to view 0 as a Float or Double to no avail, so 0 is a border problem that Number (NumberFormat.DecimalFormat) does not tolerate.

But this NumberFormat workaround does not resolve the assymmetry problem of Android 9 Locale.English(ZA).DecimalFormat emitting Locale.DE (comma decimal separator) but parsing only System.Primitives (decimal dot separator).

Incidentally, getting past the DecimalFormat problem exposed a myriad of other problems under this new-fangled English.ZA, of my App assuming system primitives working equally well with native resources. Well semantics so used require string comparison to work between primitive and native!

For example system file Primitive path names rendered in Native generating 'file not found', or even more problematic, using primitive string keys semantically only to being rendered meaningless on Native lookup.

I'm not sure which is the lesser evil, assymmetric locale English.ZA or my use of Primitives in semantics to thrust upon Natives. A futile exercise!

Right now I'm embarking on separating system primitives, including their semantic variants from ANY Native language resource strings ...

My lifetime of programming under system primitives needs an overall makeover.

Maybe I can keep an Assets repository for the primitives (resource or semantic) and have Natives look that up for system resources or for semantic Meaning.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM