【问题标题】:Having this error of java.lang.ArrayIndexOutOfBoundsException which stops me from continue my loop iteration有这个 java.lang.ArrayIndexOutOfBoundsException 错误阻止我继续我的循环迭代
【发布时间】:2019-11-02 08:09:21
【问题描述】:

我正在处理我的任务并尝试从我的文本文件中读取数据。当我试图将这些信息一个一个地存储到不同的数组时,会发生这样的错误

但是通过控制台输出,它显示它实际上确实运行了第一次迭代,但是它发生了这个错误并停止它

这是我下面的代码

public static void readFile() {

    cucibleID = new String[100];
    name = new String[100];
    matricNo = new String[100];
    date = new String[100];
    spvName = new String[100];

    try {
        Scanner sc = new Scanner(file);

        while(sc.hasNext()) {
            String readLine = sc.nextLine();



            String[] splitted = readLine.split("\t");

            for(int i=0,j=0; i< splitted.length;i++) {

                cucibleID[i] = splitted[j++];
                name[i] = splitted[j++];
                matricNo[i] = splitted[j++];
                date[i] = splitted[j++];
                spvName[i] = splitted[j++];

                System.out.println(cucibleID[i] +" "+ name[i]);
            }

        }

    }catch(Exception e) {
            e.printStackTrace();
        }
    }


这是我在控制台中的错误输出....(备注:1L5 John 来自System.out.println(cucibleID[i] +" "+ name[i]);

1L5 John
java.lang.ArrayIndexOutOfBoundsException: 5
    at ASSN1.main.readFile(main.java:99)
    at ASSN1.main.main(main.java:59)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)


【问题讨论】:

  • for 循环的意义何在?你为什么要 X 次提取 5 个值?重新考虑你在做什么,例如i 变量应该为外部while 循环的每次迭代增加一次,并且不应该有内部循环,因为您知道(好吧,期望)每行有 5 个值,您只需直接获取它们,如cucibleID[i] = splitted[0];,因为 cucibleID 是该行中的第一个值。
  • 与您的上一个问题非常相似,这个问题没有包含足够的信息来识别问题。我可以做出有根据的猜测,但它仍然只是:猜测。您最好将文件内容包含到包含John 内容的行之后。 (我的猜测是,在每次循环迭代开始时不将 j 重置为 0 会使您尝试引用不存在的拆分部分(第二次迭代是指第一次有读取访问权限时的第五部分数组)。)
  • 哦,是的,我想我有一些严重的逻辑问题。谢谢安德烈亚斯
  • 谢谢 fabian 我想我明白你的意思了
  • 其实索引 5 是第 6 部分...有点不专心...

标签: java java-io


【解决方案1】:

你的代码应该是这样的:

public static void readFile() throws IOException {
    cucibleID = new String[100];
    name = new String[100];
    matricNo = new String[100];
    date = new String[100];
    spvName = new String[100];
    try (BufferedReader in = Files.newBufferedReader(file.toPath())) {
        String line;
        for (int i = 0; (line = in.readLine()) != null; i++) {
            String[] splitted = line.split("\t");
            cucibleID[i] = splitted[0];
            name[i] = splitted[1];
            matricNo[i] = splitted[2];
            date[i] = splitted[3];
            spvName[i] = splitted[4];
            System.out.println(cucibleID[i] +" "+ name[i]);
        }
    }
}

Scanner 更改为BufferedReader,因为Scanner 非常慢。

【讨论】:

    【解决方案2】:

    让我解释一下,你的 for-each 循环是做什么的。假设您的拆分数组的长度为 5。

    第一次迭代:

    • i = 0; j = 0;
    • 与 cucibleID 一致 -> i = 0; j = 0;j++ 意味着 j 将是j = 1;
    • 与名称对应的行 -> i = 0; j = 1;j++ 这意味着 j 将是 j = 2;
    • 与matricNo的行 -> i = 0; j = 2;j++ 这意味着j 将是j = 3;
    • Line with date -> i = 0; j = 3;j++ 这意味着 j 将是 j = 4;
    • 与 spvName 对齐 -> i = 0; j = 4;j++ 这意味着 j 将是 j = 5;
    • 第一次迭代结束。 i = 0 -> i &lt; 7 -> i++

    第二次迭代

    • i = 1; j = 5;
    • 带有 cucibleID 的行 -> i = 0; j = 5; 并且 ArrayIndexOutOfBound 将发生

    您可以从我的示例中看到以下内容: 您的拆分数组具有正确的索引i,但您使用j 作为索引。 以下代码将在索引 0 处正确设置您的数组,假设您的拆分数组有 5 个元素

    int i = 0;
    int j = 0; 
    if(splitted.length == 5) {
        cucibleID[i] = splitted[j++];
        name[i] = splitted[j++];
        matricNo[i] = splitted[j++];
        date[i] = splitted[j++];
        spvName[i] = splitted[j++];
    }
    

    【讨论】:

      【解决方案3】:

      您不需要 for 循环。将j 用于拆分记录中的元素。 j 对于每条记录都应该从 0 开始。 对已处理的记录使用i

      您不得不添加一些额外的逻辑来处理少于 5 个元素的记录

      public static void readFile() {
      
          cucibleID = new String[100];
          name = new String[100];
          matricNo = new String[100];
          date = new String[100];
          spvName = new String[100];
          int i = 0;
      
          try {
              Scanner sc = new Scanner(file);
      
              while(sc.hasNext()) {
                  String readLine = sc.nextLine();
                  String[] splitted = readLine.split("\t");
                  int j = 0;
      
                  cucibleID[i] = splitted[j++];
                  name[i] = splitted[j++];
                  matricNo[i] = splitted[j++];
                  date[i] = splitted[j++];
                  spvName[i] = splitted[j++];
      
                  System.out.println(cucibleID[i] +" "+ name[i]);
      
                  i++;
      
              }
      
          }catch(Exception e) {
              e.printStackTrace();
          }
      }
      

      【讨论】:

      • 我只是冒昧地为j 添加了一个声明变量声明,并为i 修复了一个。如果您不想回到您的版本,您可以回滚编辑...
      【解决方案4】:

      在访问数组索引之前添加检查

        String[] splitted = readLine.split("\t");
       for(int i=0,j=0; i< splitted.length;i++) 
      { 
        if(splitted.length > j)
          cucibleID[i] = splitted[j++]; 
       if(splitted.length > j)
          name[i] = splitted[j++]; 
      if(splitted.length > j)
          matricNo[i] = splitted[j++]; 
      if(splitted.length > j)
          date[i] = splitted[j++]; 
      if(splitted.length > j)
          spvName[i] = splitted[j++];     
        if(cucibleID.length >i && name.length >i)
        System.out.println(cucibleID[i] +" "+ name[i]);
       }
      

      【讨论】:

      • 不能在for循环头中使用splitted,如果它被声明在inside循环中。此外,多次拆分同一个readLine有什么意义?
      • 我试过了,但输出还是一样的哥们..但感谢帮助p
      • 因为文本文件中的行后面是 id、name、matricNo、date、spvName 和 \t 作为分隔符这就是为什么我将它们拆分并单独保存到数组中。或者有没有更好的办法?
      • 我很确定这会消除异常,但不会导致 Ng Jing Xuan 期望的行为。在这种情况下,这似乎是一种 CSV(制表符)代替逗号。
      • 好吧,如果输入数据出现问题,源代码无法修复,它只能优雅地处理问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多