我有以下代码尝试确定文件的尺寸,但是每次执行时都会出现此错误:

Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)


我不知道为什么会这样。谁能帮助调试问题?并解释为什么会这样吗?

public void loadDistances(String fname) throws Exception {
    String file = fname;
    File f = new File(file);
    Scanner in = null;

    try {
        in = new Scanner(f);
    }
    catch (FileNotFoundException ex) {
        System.out.println("Can't find file " + file);
        System.exit(1);
    }

    int rows = 0;
    int cols = 0;
    int elements = 0;

    while(in.hasNext()){
        while(in.next() != null){
            System.out.println(elements++);
        }
        in.nextLine();
        rows++;
    }
    in.close();

    cols = (elements + 1) / rows;

    // for debug purposes
    System.out.println(rows);
    System.out.println(cols);
}


哪个读入此文件

0 2 3.0
1 0 2.0
2 1 7.0
2 3 1.0
3 0 6.0


//检查建议的答案

    int tokens = 0;
    String line;
    Scanner tokenScanner;
    Scanner fileScanner;
    Scanner lineScanner;

    while(fileScanner.hasNextLine()){
        line = fileScanner.nextLine();
        lineScanner.nextLine() = line;
        while(lineScanner.hasNext()){
            tokens++;
        }
        rows++;
    }

最佳答案

您不仅没有在扫描循环中为变量分配任何数据,而且不仅如此,而且您在两次仅对数据进行一次检查时从扫描器读取了数据,这是很危险的事情。

while(in.hasNext()){                 // **** checking once ****
    while(in.next() != null){        // **** read in and waste a token here!
        System.out.println(elements++);
    }
    in.nextLine();   // **** read in and waste a line here
    rows++;
}
in.close();


我会:


使用两个Scanner变量,其中一个是fileScanner,以读取文件中每一行文本,...
一个叫lineScanner的人读取行中的每个令牌。
我将使用一个外部while循环,该循环检查fileScanner.hasNextLine(),然后调用nextLine()将行读入一个字符串,称为line
然后,我将使用创建的String行创建一个新的Scanner,并将其分配给lineScanner变量。
我将使用一个内部while循环,该循环在lineScanner.hasNext()时循环,并将数据读入您的变量中。
我将在外部while循环的末端关闭内部lineScanner,以免浪费资源。




或者,您可以使用String#split(...)在读入的行中拆分标记,然后将字符串解析为数字。例如,

public List<RowData> loadDistances(String fname)
     throws FileNotFoundException, NumberFormatException {
  File file = new File(fname);
  Scanner fileScanner = new Scanner(file);
  List<RowData> rowList = new ArrayList<RowData>();

  while (fileScanner.hasNextLine()) {
     String line = fileScanner.nextLine();
     String[] tokens = line.split("\\s+");
     if (tokens.length != 3) {
        // throw some custom exception
     }

     int rowNumber = Integer.parseInt(tokens[0].trim());
     int xData = Integer.parseInt(tokens[1].trim());
     double yData = Double.parseDouble(tokens[2].trim());
     rowList.add(new RowData(rowNumber, xData, yData));
  }

  if (fileScanner != null) {
     fileScanner.close();
  }

  return rowList;
}




编辑
通过使用行扫描程序,我建议创建第二个扫描程序,传入从第一个扫描程序获得的行,并从第二个扫描程序中提取数据。如果您不知道预期要使用多少个令牌,可以使用while循环,但是您的数据似乎定义正确,每行包含一个int,int和double,我们可以使用此信息来帮助我们提取适当的数据。您可以使用类似以下的代码:

 // use previous same code as above except in the while loop:
 while (fileScanner.hasNextLine()) {
     String line = fileScanner.nextLine(); // get line
     Scanner lineScanner = new Scanner(line);  // create Scanner with it
     int rowNumber = 0;
     int xData = 0;
     double yData = 0.0;

     if (lineScanner.hasNextInt()) {
        rowNumber = lineScanner.nextInt();
     } else {
        // throw a custom exception since int not found
     }
     if (lineScanner.hasNextInt()) {
        xData = lineScanner.nextInt();
     } else {
        // throw a custom exception since int not found
     }
     if (lineScanner.hasNextDouble()) {
        yData = lineScanner.nextDouble();
     } else {
        // throw a custom exception since double not found
     }

     rowList.add(new RowData(rowNumber, xData, yData));

     if (lineScanner != null) {
        lineScanner.close();
     }
  }

09-06 00:36