Java程序抛出NumberFormatException,如何修复销售报表程序?
Java NumberFormatException 错误修复方案
报错信息
Exception in thread "main" java.lang.NumberFormatException: For input string: "" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Integer.parseInt(Integer.java:662) at java.base/java.lang.Integer.parseInt(Integer.java:770) at Main.displayBody(Main.java:27) at Main.main(Main.java:11)
需求说明
需编写包含main()、displayHeader()、displayBody()、displayFooter()的程序:
main()调用另外三个方法displayHeader()打印报表头部displayBody()读取Lab6Data.txt,打印主体并累计总数,直到读取到quitdisplayFooter()打印总计
预期输出:
Sales Report Name..........Amount Abbot.......2,685 Coswell.....1,745 Freedwick...6,283 Gibson......5,453 Total......16,166
Lab6Data.txt 内容
Abbot 2685 Coswell 1745 Freedwick 6283 Gibson 5453 quit 0
用户编写的代码
import java.util.Scanner; class Main { public static void main(String[] args) { displayHeader(); displayBody(); displayFooter(); } public static void displayHeader() { String header = ""; Scanner sc = new Scanner(System.in); System.out.println("Sales Report"); System.out.println("Name......Amount"); } public static void displayBody() { String throwaway = ""; Scanner sc = new Scanner(System.in); while (sc.hasNextLine()) { String name = sc.nextLine(); throwaway = sc.nextLine(); if (name.equals("quit")) break; int amount = Integer.parseInt(sc.nextLine()); throwaway = sc.nextLine(); System.out.println("name......"+name+" amount"+amount); } } public static void displayFooter() { String totalSum = ""; Scanner sc = new Scanner(System.in); while(sc.hasNextLine()){ int sum =0; int total = Integer.parseInt(sc.nextLine()); sum += total; System.out.println("Total....." + sum); } } }
问题分析与修复步骤
1. 核心错误原因
报错源于displayBody()中错误地重复调用sc.nextLine(),跳过了有效数据行,导致Integer.parseInt()读取到空字符串或不符合要求的内容。原代码每次循环读取4行,但实际数据是姓名、金额交替存储,完全不需要额外的"丢弃行"操作。
2. 具体修复点
(1)修正displayBody()的读取逻辑
- 移除所有多余的
throwaway = sc.nextLine();语句,每次循环仅读取姓名行和对应的金额行 - 新增静态变量存储累计总金额,让
displayBody()和displayFooter()可以共享数据 - 读取目标文件而非标准输入,原代码错误地读取控制台输入,需改为读取
Lab6Data.txt - 格式化金额输出,添加千位分隔符并对齐格式,匹配预期输出
(2)清理displayHeader()冗余代码
- 移除无用的
Scanner sc = new Scanner(System.in);,该方法仅需打印内容,无需读取输入
(3)重构displayFooter()逻辑
- 无需重新读取输入,直接使用
displayBody()累计的总金额,格式化输出总计
3. 完整修复后的代码
import java.util.Scanner; import java.text.NumberFormat; import java.util.Locale; class Main { // 静态变量存储总金额,实现方法间数据共享 private static int totalAmount = 0; public static void main(String[] args) { displayHeader(); displayBody(); displayFooter(); } public static void displayHeader() { System.out.println("Sales Report"); System.out.println("Name..........Amount"); } public static void displayBody() { // 读取Lab6Data.txt文件,使用try-with-resources自动关闭流 try (Scanner sc = new Scanner(Main.class.getResourceAsStream("Lab6Data.txt"))) { NumberFormat amountFormatter = NumberFormat.getNumberInstance(Locale.US); while (sc.hasNextLine()) { String name = sc.nextLine().trim(); // 跳过可能存在的空行 if (name.isEmpty()) continue; // 遇到quit则终止循环 if (name.equals("quit")) break; // 读取对应金额行,避免无数据时抛出异常 if (!sc.hasNextLine()) break; String amountStr = sc.nextLine().trim(); int amount = Integer.parseInt(amountStr); totalAmount += amount; // 格式化对齐输出 System.out.printf("%-10s%s%n", name, amountFormatter.format(amount)); } } catch (Exception e) { e.printStackTrace(); } } public static void displayFooter() { NumberFormat amountFormatter = NumberFormat.getNumberInstance(Locale.US); System.out.printf("Total......%s%n", amountFormatter.format(totalAmount)); } }
4. 关键说明
- 文件读取修正:确保
Lab6Data.txt与编译后的class文件在同一目录,使用类加载器流读取文件 - 异常防护:添加空行跳过逻辑、数据存在性判断,避免因文件格式问题抛出异常
- 输出格式化:用
printf实现文本对齐,NumberFormat生成带千位分隔符的金额格式 - 资源自动管理:使用try-with-resources语法自动关闭Scanner,避免资源泄漏
内容的提问来源于stack exchange,提问作者user20217226
相关产品推荐
相关产品推荐

