Java如何将含姓名与两个数值的字符串拆分为String和两个double变量
错误原因分析
你遇到的java.util.InputMismatchException异常,本质是Scanner尝试读取的内容和你指定的目标数据类型不匹配,异常抛出点在nextDouble()调用,说明此时Scanner拿到的分词结果不是合法的double格式,核心错误来自两处:
- Scanner初始化位置错误
你仅在进入while循环前,用读取到的第一行文本创建了一次Scanner对象。后续循环中你虽然通过inFile.readLine()拿到了新的行内容,但并没有把新行同步给Scanner处理。当第一行的4个分词(名、姓、两个double数值)读完后,Scanner已经没有可解析的有效内容,下一轮循环再调用scan.next()或scan.nextDouble()时,要么直接读取失败,要么拿到的内容不是预期的数值类型,自然触发类型不匹配异常。 - 缺少异常边界判断(次要原因)
你没有提前判断当前行是否有足够的分词、分词是否符合数值格式,哪怕出现某行内容残缺、格式错误的情况,程序也会直接抛出异常。
另外还有低概率的区域格式问题:如果你的系统默认区域设置的小数分隔符是逗号而非点,读取3.36这类带小数点的数值时也会触发该异常。
修复方案
最简单的修改是把Scanner的创建逻辑挪到while循环内部,每读取一行就创建一个新的Scanner绑定当前行内容,修改后的代码如下:
public Roster(String filename) { players = new ArrayList<Player>(); try (FileReader fr = new FileReader(filename); BufferedReader inFile = new BufferedReader(fr)) { String line = inFile.readLine(); while(line != null) { // 每一行单独创建Scanner处理 Scanner scan = new Scanner(line); String firstName = scan.next(); String lastName = scan.next(); double attackStat = scan.nextDouble(); double blockStat = scan.nextDouble(); String name = firstName + " " + lastName; Player newPlayer = new Player(name, attackStat, blockStat); players.add(newPlayer); scan.close(); line = inFile.readLine(); } } catch (IOException e) { System.out.println(e); } }
如果确认是区域格式问题,可以在创建Scanner后指定区域设置:scan.useLocale(Locale.US);
内容的提问来源于stack exchange,提问作者Austin Garbacz
相关产品推荐
相关产品推荐

