【问题标题】:Basic file scanner exception/issue基本文件扫描程序异常/问题
【发布时间】:2015-10-25 23:43:46
【问题描述】:

我正在为我的班级编写一个程序,要求我从 txt 文件中读取数据,然后将其显示回来。我创建了一个读取 hasNext 的 while 循环,但我遇到了异常。它说这是“没有这样的元素例外”,我不知道为什么。循环工作 5 次迭代,然后给我异常

import java.util.Scanner;
import java.text.DecimalFormat;
import java.io.*;

public class Project2_William_Walker
{
    public static void main (String[]args) throws IOException
    {
      File file = new File ("boarding.txt");
      Scanner inputFile = new Scanner(file);
      DecimalFormat df = new DecimalFormat("0.00");

      String title = "Madison Kennel & Grooming";   
      String fName;
      String lName;
      String breed;
      String weight;
      String age;
      double highRisk = 20.00;




      while (inputFile.hasNext())
      {
         fName = inputFile.nextLine();
         lName = inputFile.nextLine();
         breed = inputFile.nextLine();
         weight = inputFile.nextLine();
         age = inputFile.nextLine();

         inputFile.nextLine();

         System.out.println(fName + " " + lName + " " + breed + " " + weight + " " + age);
         System.out.println();



      }
      inputFile.close();    

      System.out.println("End of Program");

   }
}

所以在我的 txt 文件中,我有一个列表,其中包含名字、姓氏、品种、体重和年龄。看起来像这样:

Will  
Walker  
Pug  
3  
4  

John  
Appleseed  
Retriever  
15  
7  

..等等还有 4 个条目。我的循环通过前 5 次就好了,但在第 6 次也是最后一次通过。感谢您的帮助!

【问题讨论】:

  • 请注意,如果您对异常有疑问,发布整个异常及其堆栈跟踪非常重要。因此,请将其添加到您的问题中。

标签: java exception java.util.scanner


【解决方案1】:

您正在循环中读取 6 行,但循环条件仅检查是否有(至少)1 行要读取。

您可能在输入文件的末尾有一个额外的空白行,这导致hasNext() 在读取最后一个数据块后返回true

您最好使用 for 循环迭代 5 次,每次检查是否有可用的行,每次将数据保存到数组中。

类似:

String[] data = new String[5];

while (inputFile.hasNext()) {
    Arrays.fill(data, null); // clear out array, in case input is short
    for (int i = 0; i < 5 && inputFile.hasNext(); i++)
        data[i] = inputFile.nextLine();

    if (inputFile.hasNext())
        inputFile.nextLine();

    System.out.println(data[0] + " " + data[1] + " " + data[2] + " " + data[3] + " " + data[4]);
    System.out.println();
}
inputFile.close();    

【讨论】:

  • "但是循环条件只检查是否有(至少)1行要读取"这不会是一个问题(但仍然有代码味道和容易出错)如果最后一个块不只包含行...:P。而这个"You might have a blank line at the end of the input file"会解决他的问题。
  • @Tom 哎呀!你是对的。我完全忘记了所需的额外检查。希望现在看起来更好。
  • 是的,这样更好:D。可惜你错过了它,因为我还写了一个答案来解释 OP 如何修复它(因为你错过了:P),但它现在已经过时了。
  • @Tom 您的回答非常好(值得赞)而且没有过时。有两个几乎相同的答案是可以的 - 一起解释同一件事的不同方式可能比单独使用任何一种方式更有帮助。
  • 感谢两位的帮助!
【解决方案2】:

让我们找出问题的根源。为了轻松做到这一点,让我们将您的 nextLine() 调用“映射”到文件内容:

Iteration  Code                              Read line from file

   1       fName = inputFile.nextLine();     Will
   1       lName = inputFile.nextLine();     Walker
   1       breed = inputFile.nextLine();     Pug
   1       weight = inputFile.nextLine();    3
   1       age = inputFile.nextLine();       4
   1       inputFile.nextLine();             (empty line between blocks)
   2       fName = inputFile.nextLine();     John
   2       lName = inputFile.nextLine();     Appleseed
   2       breed = inputFile.nextLine();     Retriever
   2       weight = inputFile.nextLine();    15
   2       age = inputFile.nextLine();       7
   2       inputFile.nextLine();             

如您所见,最后一条语句 inputFile.nextLine() 尝试从文件中读取一行,但没有更多内容可读取,因为 "7" 是最后一行。所以你的问题是你希望在一个块之后总是一个空行。

快速解决方法是添加检查,如下所示:

if (inputFile.hasNextLine())
    inputFile.nextLine();

但是,如果没有空行来分割两个块,并且下一个块在最后一个块之后开始,这可能会导致麻烦。

为了首先避免此类问题,我建议使用不同的文件结构。例如,您可以使用带有“,”的csv 作为分隔符:

威尔,沃克,帕格,3,4
John,Appleseed,Retriever,15,7

然后这样读:

final String line = inputFile.nextLine(); // read a single line
final String[] items = line.split(",");  // split that line using ','
fName = items[0];
lName = items[1];
breed = items[2];
weight = items[3];
age = items[4];
System.out.println(fName + " " + lName + " " + breed + " " + weight + " " + age);

为了让它变得更好:创建一个模型类,它包含表示这样一行(或您以前的文件样式的一个块)的必要字段,并让像 Jackson 这样的 csv 阅读器为您进行解析。

【讨论】:

  • 这正是我的问题!非常感谢你的帮助!像这样绘制它真的很有帮助,我对编程真的很陌生,所以通过可视化我能够马上看到我的问题。
猜你喜欢
  • 1970-01-01
  • 2010-12-31
  • 2012-05-20
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多