ArrayIndexOutOfBoundsException异常排查:CSV转ArrayList报错
问题:读取CSV文件存入ArrayList时抛出ArrayIndexOutOfBoundsException异常
尝试读取CSV文件(内容为C,John,Goh,0031)并将数据存入ArrayList,运行时持续抛出异常:ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 1。相关代码如下:
核心处理方法代码
public static boolean processNewData(ArrayList<Student> studList, String filename) { File infile = new File(filename); Scanner reader = null; boolean addStudent = true; boolean success = false; try { reader = new Scanner(infile); while (reader.hasNextLine()) { String row = reader.nextLine(); String[] data = row.split(","); if (studList.size() == 0) { addStudent = true; } else if (studList.size() > 0) { // Check if student number exist in the student arraylist for (Student s : studList) { if (s.getStudNo() == Long.parseLong(data[3])) { addStudent = false; throw new StudentException("Student Number Exist...."); } else { addStudent = true; continue; } } } if (addStudent == true) { if (data[0].compareToIgnoreCase("C") == 0) { Student_Course s1 = new Student_Course( data[1], data[2], Long.parseLong(data[3]) ); success = true; studList.add(s1); } else if (data[0].compareToIgnoreCase("R") == 0) { Student_Research s1 = new Student_Research( data[1], data[2], Long.parseLong(data[3]) ); success = true; studList.add(s1); } else { // If the enrolement is neither C or R, print the student ID and show the enrolement type // Continue to add the rest System.out.println(); System.out.println("Student Number: " + data[3] + " from file with invalid type - " + data[0]); success = false; continue; } } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (StudentException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } } return success; }
Student_Course类代码
public class Student_Course extends Student { private Unit_Course unitCourse; private String enrolementType; public Student_Course(String fName, String lName, long studNo) { super(fName, lName, studNo); enrolementType = "C"; } }
异常原因分析
这个异常明确说明:你尝试访问数组下标3,但数组实际长度只有1。这意味着某一行CSV数据经过split(",")分割后,只得到了1个元素,而非预期的4个字段。
最可能的触发场景:
- CSV文件中存在空行:空行调用
split(",")会返回长度为1的数组(元素为空字符串)。 - 存在格式错误的行:比如某一行没有使用逗号分隔,整行作为一个元素存入数组。
除此之外,代码还有几个潜在问题会导致逻辑异常:
- 重复学生检查逻辑错误:只要找到一个不重复的学生,就会把
addStudent设为true并跳过后续检查。如果列表中前面的学生不重复,但后面有重复的,会漏掉重复判断,导致重复学生被添加。 - 抛出
StudentException后直接终止循环:后续行无法继续处理,中断整个文件读取流程。 - 未妥善关闭
Scanner资源:可能导致资源泄漏。
修复方案
1. 过滤空行与无效格式行
在分割前先处理空行,分割后检查数组长度是否符合预期,不符合则跳过并提示:
while (reader.hasNextLine()) { String row = reader.nextLine().trim(); // 去除行首尾空白字符 if (row.isEmpty()) { continue; // 跳过空行 } String[] data = row.split(","); if (data.length != 4) { System.out.println("跳过格式无效的行:" + row); continue; } // 后续业务逻辑... }
2. 修正重复学生检查逻辑
先默认允许添加,找到重复项后标记为不允许并跳出循环,避免中途覆盖标记:
addStudent = true; // 默认允许添加 if (!studList.isEmpty()) { for (Student s : studList) { if (s.getStudNo() == Long.parseLong(data[3])) { addStudent = false; System.out.println("学生编号已存在:" + data[3]); break; // 找到重复项后立即退出循环,无需继续检查 } } }
如果不需要中断整个流程,建议移除throw new StudentException,改为控制台提示即可。
3. 使用try-with-resources自动关闭资源
替换手动关闭Scanner的逻辑,确保资源自动释放:
try (Scanner reader = new Scanner(infile)) { // try-with-resources会自动关闭资源 while (reader.hasNextLine()) { // 循环逻辑... } } catch (FileNotFoundException e) { System.out.println("文件未找到:" + filename); return false; } catch (StudentException e) { e.printStackTrace(); }
4. 处理学号前导零(可选)
Long.parseLong("0031")会将其转换为数值31,丢失前导零。如果需要保留前导零的字符串形式,需要修改Student类的学号字段类型为String,并调整相关方法的参数与返回值。
内容的提问来源于stack exchange,提问作者Aloysious Kok
相关产品推荐
相关产品推荐

