Java 中非默认语言环境的 NumberFormat 解析不正确
Posted
技术标签:
【中文标题】Java 中非默认语言环境的 NumberFormat 解析不正确【英文标题】:NumberFormat incorrect parse for non default locale in java 【发布时间】:2017-10-05 05:21:12 【问题描述】:NumberFormat 错误地解析了默认 en_US 以外的区域设置的数字。例如,对 fr_CA 的解析给出了不正确的结果。
NumberFormat nf = NumberFormat.getNumberInstance(new Locale("fr_CA"));
Number num = nf.parse("2.302,52");
输出为:2.302
预期输出:2302,52
或 2302.52
基本上是把这个数字的值从 2000 变成了 2,这是不正确的。
详情请看以下截图:
我无法识别出了什么问题,请帮忙!
【问题讨论】:
@Jens:一定要注意这个值不对,必须是2302.52,内部表示不能改变值! @Jens:既然你已经删除了你的评论,你能不能也修改一下你的反对票。 【参考方案1】:编辑 1:
通过将小数点和分组分隔符设置为,我能够使用 DecimalFormat 正确解析非默认语言环境值:
/**
* Testing DF parse
*/
DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(',');
symbols.setGroupingSeparator('.');
df.setDecimalFormatSymbols(symbols);
Number num = df.parse("2.302,52"); // OUTPUT is: 2302.52 -> correctly parsed
/**
* Round off and format
*/
double d = num.doubleValue();
double roundedVal = Math.round(d); // OUTPUT is: 2303.0 -> correctly rounded off
String localeAwareVlue = df.format(roundedVal); // OUTPUT is: 2.303 -> using correct grouping separator
valueString = localeAwareVlue;
但我真的希望能够在运行时动态地执行此操作,而不必为我可能收到的每种语言/国家/地区组合设置分隔符。请提供任何建议。
编辑 2:
我最终得到了以下最终代码,以便能够动态解析和格式化本地化值。这适用于 ###,###.## 和 ###.###,## 等模式 - 假设是 -
-
收到的数据总是只有 2 位小数
小数分隔符可以是逗号或句点
分组分隔符可以是句点或逗号
String localValue = args.get(0).toString();
// String locale = args.get(1).toString();
char decChar = localValue.charAt(localValue.length()-3);
char grpChar = ',';
if(decChar == ',')
grpChar = '.';
DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(decChar);
symbols.setGroupingSeparator(grpChar);
df.setDecimalFormatSymbols(symbols);
Number parsedValue = 0;
try
parsedValue = df.parse(localValue);
catch (ParseException pe)
pe.printStackTrace();
/**
* Round off and format to localize
*/
double roundedValue = Math.round(parsedValue.doubleValue());
String localeAwareValue = df.format(roundedValue);
// TODO - use Locale with nf instead of above method
// currently facing issue with incorrect parse for non default locale
/*
NumberFormat nf = NumberFormat.getInstance(new Locale(locale));
Number num = nf.parse(localValue);
*/
不用说我对解决方案不满意,这更像是一种解决方法,直到我得到主要问题的解决方案 - NumberFormat 对非默认语言环境的错误解析。因此,仍然欢迎任何提示、建议和解决方案。
【讨论】:
【参考方案2】:这里有两个问题,
1) 您创建的语言环境不正确。使用Locale.CANADA_FRENCH
。
2) 给定数字在默认和加拿大语言环境中均无效。根据ICU,在fr_CA
中,分组分隔符为空,小数分隔符为,
。
因此,在您的示例中,它使用默认语言环境,它将.
视为小数分隔符并在,
处保释,而在正确的语言环境中,它将在.
处保释并简单地返回@987654328 @。
在fr_CA
中写入这个数字的正确方式是2302,52
所以,真的,Java 是正确的,但你对这个数字格式的假设是不正确的。
【讨论】:
以上是关于Java 中非默认语言环境的 NumberFormat 解析不正确的主要内容,如果未能解决你的问题,请参考以下文章
Sonar以Sonar默认语言环境之外的其他语言显示违规消息