Java运行时异常:ArrayIndexOutOfBoundsException(索引130越界)求助
解决Java数组越界异常(ArrayIndexOutOfBoundsException)的问题
错误原因分析
你遇到的Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 130 out of bounds for length 130异常,直接触发点在init方法的第55行:variableinput[i] = (char) c;。当i的值走到130时,超出了variableinput数组的合法索引范围(数组长度130,索引只能是0-129),具体原因有这几个:
- 超长行未处理:输入文件里存在某一行的字符数超过129个,当读取到第130个字符时,
i自增到130,赋值时直接越界。 - 换行符处理不完整:Windows系统的换行是
CR(13)+LF(10)组合,你的代码只把LF(10)当作换行标志。当读取到CR(13)时,会先把它存入数组让i自增,如果此时数组已经被填满(i=129),加上这个CR就会让i=130,下一次赋值就触发异常。 - 无边界限制逻辑:代码里没有限制
i的最大值,哪怕数组已经满了,还是会继续往里面写数据,必然触发越界。
最优解决方案:改用按行读取(规避手动字符处理的坑)
手动逐个字符读取并维护数组的方式很容易出错,推荐用BufferedReader的readLine()方法按行读取文件——这样能直接拿到每一行的完整字符串,完全不用操心数组长度不够的问题。修改后的代码如下:
import java.io.*; public class Datachange { public class variables { private char [] body; private int ID; private int population; private int populationchilds; private int populationchildspoverty; private double populationchildpovertypercent; variables(char [] input) { body = input; // 先做长度检查,避免后续截取数组时越界 if (body.length < 108) { throw new IllegalArgumentException("输入行长度不足,无法解析数据"); } char[] stateID = java.util.Arrays.copyOfRange(body,0,2); ID = Integer.parseInt(new String(stateID).trim()); char[] totalpopulation = java.util.Arrays.copyOfRange(body,83,90); population = Integer.parseInt(new String(totalpopulation).trim()); char [] childpopulation = java.util.Arrays.copyOfRange(body,92,99); populationchilds = Integer.parseInt(new String(childpopulation).trim()); char [] povertychilds = java.util.Arrays.copyOfRange(body,101,108); populationchildspoverty = Integer.parseInt(new String(povertychilds).trim()); } } public static void main(String[] args) { Datachange DS = new Datachange(); DS.init(); } public void init() { variables dataframe[] = new variables[13486]; try (BufferedReader inputDataframe = new BufferedReader(new FileReader("SmallAreaIncomePovertyEstData.txt"))) { String line; int j = 0; while((line = inputDataframe.readLine())!=null) { // 直接把行字符串转成char数组,自动适配每行长度 char variableinput[] = line.toCharArray(); dataframe[j] = new variables(variableinput); j++; // 防止读取行数超过数组容量 if (j >= dataframe.length) { System.out.println("数据行数超过数组上限,已停止读取"); break; } } } catch(IOException except) { System.out.println("There is Input/Output Error:" + except.getMessage()); } this.newdata(dataframe); } public variables[] newdata(variables[] dataset) { variables[] newdata=new variables[57]; try (BufferedWriter outData = new BufferedWriter(new FileWriter("SmallAreaIncomePovertyEstDatanew.txt"))) { int stateID = 1; //First ID int statePop= 0; int stateChdPop=0; int stateChdPovertyPop=0; // 只处理已初始化的数组元素 for(int i=0;i<dataset.length && dataset[i]!=null;i++) { if (dataset[i].ID == stateID) { statePop += dataset[i].population; stateChdPop += dataset[i].populationchilds; stateChdPovertyPop += dataset[i].populationchildspoverty; } else { double stateChdPovertyPopPercent=0; if (stateChdPop != 0) { stateChdPovertyPopPercent = (double) stateChdPovertyPop/stateChdPop * 100; } else { stateChdPovertyPopPercent = 0; } outData.append(stateID + "\t" + statePop + "\t" + stateChdPop + "\t" + stateChdPovertyPop+ "\t" + stateChdPovertyPopPercent + "\n"); statePop = 0; stateChdPop = 0; stateChdPovertyPop = 0; i--; stateID++; } } // 补充写入最后一个州的统计数据 double stateChdPovertyPopPercent=0; if (stateChdPop != 0) { stateChdPovertyPopPercent = (double) stateChdPovertyPop/stateChdPop * 100; } else { stateChdPovertyPopPercent = 0; } outData.append(stateID + "\t" + statePop + "\t" + stateChdPop + "\t" + stateChdPovertyPop+ "\t" + stateChdPovertyPopPercent + "\n"); } catch(IOException except) { System.out.println("I/O Error:" + except.getMessage()); } return newdata; } }
额外优化说明
- 在
variables构造函数里加了行长度检查,避免因行太短导致copyOfRange操作触发新的越界异常。 init方法里增加了数组容量校验,防止读取的行数超过dataframe的初始化长度。newdata方法的循环里增加了dataset[i]!=null判断,避免处理未初始化的空数组元素。- 补充了最后一个州的数据写入逻辑——原代码会漏掉最后一组州的统计结果。
内容的提问来源于stack exchange,提问作者Kj Analytica
相关产品推荐
相关产品推荐

