简体   繁体   English

将文件读入2D数组时出错

[英]Error when reading file into 2D array

I have the following code which tries to determine the dimensions of a file, but each time it executes through there is this error: 我有以下代码尝试确定文件的尺寸,但是每次执行时都会出现此错误:

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

I'm unaware why this is occurring. 我不知道为什么会这样。 Can anyone help debug the issue? 谁能帮助调试问题? And explain why it is happening? 并解释为什么会这样吗?

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);
}

Which reads in this file 哪个读入此文件

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

// Checking for suggested answer //检查建议的答案

    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++;
    }

You assign no data to your variables at all in your scanning loop, and not only that, but you read from the Scanner twice while checking it for data only once , a dangerous thing to do. 您不仅没有在扫描循环中为变量分配任何数据,而且不仅如此,而且在仅一次扫描一次以检查数据的情况下从扫描器读取了两次 ,这很危险。

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();

I would: 我会:

  • Use two Scanner variables, one, fileScanner, to read in each line of text in the file,... 使用两个Scanner变量,其中一个为fileScanner,以读取文件中每一行文本,...
  • And one called lineScanner to read in each token on the line. 一个叫lineScanner的人读入行中的每个令牌。
  • I'd use an outer while loop, that checks fileScanner.hasNextLine() , and then calls nextLine() to read the line into a String, say called line . 我将使用一个外部while循环,该循环检查fileScanner.hasNextLine() ,然后调用nextLine()将该行读入一个String中,称为line
  • I'd then create a new Scanner with the line of String created, and assign it into a lineScanner variable. 然后,我将使用创建的String行创建一个新的Scanner,并将其分配给lineScanner变量。
  • I'd use an inner while loop that loops while lineScanner.hasNext() , and reads in the data into your your variables. 我将使用一个内部while循环,该循环在lineScanner.hasNext()时循环,并将数据读入您的变量中。
  • I'd close the inner lineScanner at the end of the outer while loop so as not to waste resources. 我将在外部while循环的末端关闭内部lineScanner,以免浪费资源。

Alternatively, you could use String#split(...) to split the tokens in the line read in, and then parse the Strings into numbers. 或者,您可以使用String#split(...)在读入的行中拆分标记,然后将字符串解析为数字。 For example, 例如,

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;
}

Edit 编辑
By using a line Scanner, I recommend creating a second Scanner, passing in the line obtained from the first Scanner, and extracting data from this second Scanner. 通过使用行扫描程序,我建议创建第二个扫描程序,传入从第一个扫描程序获得的行,并从第二个扫描程序中提取数据。 You could use a while loop if you didn't know how many tokens to expect, but your data appears to be well defined, with each line holding an int, int, and double, and we can use this information to help us extract the proper data. 如果您不知道期望多少个令牌,可以使用while循环,但是您的数据似乎定义良好,每行包含一个int,int和double,我们可以使用此信息来帮助我们提取适当的数据。 You could use code something like this: 您可以使用类似以下的代码:

 // 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();
     }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM