java.lang.NumberFormatException: 对于输入的字符串"1,167.40",无法进行数字格式化处理。

11

我正在从CSV文件中读取数据。其中一个字段包含值1,167.40。读取此字段的代码片段如下:

String csvFilename = "TEST_FILE.csv";
CSVReader csvReader = new CSVReader(new FileReader(csvFilename));
String[] row = null;
csvReader.readNext(); // to skip the headers
while((row = csvReader.readNext()) != null) 
{
  double val = Double.parseDouble(row[0]); // !!!
}
csvReader.close();

该行代码 double val = Double.parseDouble(row[0]) 导致以下错误信息:

java.lang.NumberFormatException: For input string: "1,167.40"

如何解决这个问题?

附注:对于其他值,如111.64,不会出现此错误。


Double.parseDouble() 不喜欢你提供的字符串中有 ,。你尝试过从输入中删除 , 吗?我假设 1,167.40 和 1167.40 是相同的。 - Mateusz Andrzejewski
我猜NumberFormatException是因为逗号(,)的原因。尝试从CSV文件中去掉它。 - wns349
5个回答

16

你的输入中间的逗号,有误。一个简单粗暴的解决方案是在将其解析为double之前将其删除。

double val = Double.parseDouble(row[0].replaceAll(",", ""));

更好的解决方案是使用NumberFormat来处理:

//assumes your server already has English as locale
NumberFormat nf = NumberFormat.getInstance(); /
//...
double val = nf.parse(row).doubleValue();

替换值只是一种临时解决方案,因为它会变得非常特定于数据内容。更明智的做法是先确定区域设置并根据其格式化数据。 - Gyanendra Dwivedi
然后在您的应用程序中附上一个警告"不适用于法国" ;-) - Bathsheba
@Bathsheba 如果电脑/服务器配置了英语默认区域设置,那就没有问题。 - Luiggi Mendoza
对于您的第二个解决方案,编译器会报错“无法在基本类型double上调用doubleValue()”。 - Klausos Klausos
@KlausosKlausos 谢谢,代码已修复。 - Luiggi Mendoza

7

您应该使用本地化特定的格式:

NumberFormat nf = NumberFormat.getInstance(Locale.ENGLISH);
myNumber = nf.parse(myString);

一些国家使用逗号和点号表示千位分隔符和小数点,例如在Locale.FRENCH中“1.167,40”表示的是1千克167克4毫克,因此直接去掉逗号可能会导致错误。


3
如何获取双精度值? - Klausos Klausos

4

这是因为逗号(',')符号的原因。这里的数据是为特定地区表示的。因此,您应该首先使用本地化信息格式化十进制数据,然后再进行解析。

一个例子是:

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class JavaMain {
    public static void main(String[] args) {
        String numberString = "2.105,88";
        //using casting
        try {
            DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.GERMAN);
            df.setParseBigDecimal(true);
            BigDecimal bd = (BigDecimal) df.parseObject(numberString);
            System.out.println(bd.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
        try {
            BigDecimal bd1 = new BigDecimal(nf.parse(numberString).toString());
            System.out.println(bd1.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

3

Double.parseDouble()不支持您提供的字符串中包含,。您尝试过从输入中删除,吗?我认为1,167.40和1167.40是相同的。

您可以尝试:

double val = Double.parseDouble(row[0].replace(',' , '');

不要去掉逗号:否则会破坏欧洲大陆的语言环境(法国、德国等)。 - Bathsheba
1
@Bathsheba 这里的主要问题不在这里。 - Luiggi Mendoza
@Bathsheba 它只是将值传递给double,无论如何你都必须这样做而没有逗号。replace返回一个新的字符串,因此row[0]的原始值(我认为应该用于区域设置)不会改变。 - Mateusz Andrzejewski

3

尝试使用 NumberFormat.getInstance().parse(row[0]) 代替 Double.parseDouble()

这个建议是关于IT技术的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接