为何读取文本文件并正常打印时仍抛出NoSuchElementException?
解决CSV读取时的NoSuchElementException异常
我能读取文本文件的所有内容并打印数据,但仍会抛出NoSuchElementException异常。尝试了在while循环中使用hasNext()的方案,但没起作用。
原实现代码
public void fileReader() throws IOException { String id; String brand; int yearOfManufacture; int numSeats; double rentalPerDay; double insurancePerDay; double serviceFee; double discount; String model; String type; String color; ArrayList<Vehicle> vehicleArray = new ArrayList<>(); File file = new File("C:/Users/jockg/Downloads/Fleet (1).csv"); Scanner scan = new Scanner(file); scan.useDelimiter("n/n"); while (scan.hasNext() || scan.hasNextDouble() || scan.hasNextInt()) { id = scan.next(); System.out.println(id); brand = scan.next(); System.out.println(brand); model = scan.next(); System.out.println(model); type = scan.next(); System.out.println(type); yearOfManufacture = Integer.parseInt(scan.next()); System.out.println(yearOfManufacture); numSeats = Integer.parseInt(scan.next()); System.out.println(numSeats); color = scan.next(); System.out.println(color); rentalPerDay = Double.parseDouble(scan.next()); System.out.println(rentalPerDay); insurancePerDay = Double.parseDouble(scan.next()); System.out.println(insurancePerDay); serviceFee = Double.parseDouble(scan.next()); System.out.println(serviceFee); if (scan.next().equals("N/A")) { discount = 0; } else { discount = Double.parseDouble(scan.next()); } System.out.println(discount); Car newCar = new Car(id, brand, yearOfManufacture, numSeats, rentalPerDay, insurancePerDay, serviceFee, discount, model, type, color); vehicleArray.add(newCar); } }
CSV文件内容
C001,Toyota,Yaris,Sedan,2012,4,Blue,50,15,10,10 C002,Toyota,Corolla,Hatch,2020,4,White,45,20,10,10 C003,Toyota,Kluger,SUV,2019,7,Grey,70,20,20,10 C004,Audi,A3,Sedan,2015,5,Red,65,10,20,10 C005,Holden,Cruze,Hatch,2020,4,Green,70,10,10,10 C006,BMW,X5,SUV,2018,7,White,100,25,20,10 C007,BMW,320i,Sedan,2021,5,Grey,75,10,15,N/A C008,Ford,Focus,Sedan,2014,5,Red,45,10,10,N/A C009,Ford,Puma,SUV,2015,5,Black,70,20,15,20
问题分析
- 分隔符设置错误:
scan.useDelimiter("n/n")完全不符合CSV格式,CSV用逗号分隔字段、每行是一条完整记录,错误的分隔符会导致Scanner读取逻辑混乱。 - 循环条件逻辑错误:
scan.hasNext() || scan.hasNextDouble() || scan.hasNextInt()使用逻辑或,只要任意一个条件为真就会继续循环,即使后续已经没有可读取的元素,最终触发NoSuchElementException。 - 重复读取元素:处理discount时,
if (scan.next().equals("N/A"))调用了一次scan.next(),如果条件不成立,又会调用一次scan.next(),导致跳过一个字段,后续读取全部错位,最终无元素可读时抛出异常。
修正后的代码
public void fileReader() throws IOException { ArrayList<Vehicle> vehicleArray = new ArrayList<>(); File file = new File("C:/Users/jockg/Downloads/Fleet (1).csv"); Scanner scan = new Scanner(file); // 逐行读取每条车辆记录 while (scan.hasNextLine()) { String line = scan.nextLine(); // 按逗号分割字段,适配CSV格式 String[] fields = line.split(","); // 从分割后的数组中提取各字段 String id = fields[0]; String brand = fields[1]; String model = fields[2]; String type = fields[3]; int yearOfManufacture = Integer.parseInt(fields[4]); int numSeats = Integer.parseInt(fields[5]); String color = fields[6]; double rentalPerDay = Double.parseDouble(fields[7]); double insurancePerDay = Double.parseDouble(fields[8]); double serviceFee = Double.parseDouble(fields[9]); // 只读取一次discount字段,避免重复操作 double discount = fields[10].equals("N/A") ? 0 : Double.parseDouble(fields[10]); // 打印验证数据 System.out.println(id); System.out.println(brand); System.out.println(model); System.out.println(type); System.out.println(yearOfManufacture); System.out.println(numSeats); System.out.println(color); System.out.println(rentalPerDay); System.out.println(insurancePerDay); System.out.println(serviceFee); System.out.println(discount); // 创建车辆对象并加入集合 Car newCar = new Car(id, brand, yearOfManufacture, numSeats, rentalPerDay, insurancePerDay, serviceFee, discount, model, type, color); vehicleArray.add(newCar); } // 关闭Scanner释放资源 scan.close(); }
关键修改说明
- 逐行读取+字段分割:用
hasNextLine()判断是否还有记录,nextLine()获取整行后用split(",")拆分字段,彻底避免Scanner分隔符的混乱问题。 - 避免重复读取:处理discount时只读取一次字段值,解决原代码中重复调用
scan.next()导致的字段跳过和错位问题。 - 资源释放:添加
scan.close()关闭Scanner,避免资源泄漏。
内容的提问来源于stack exchange,提问作者happy days
相关产品推荐
相关产品推荐

