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

时间:2014-01-18 16:33:25

标签: java arrays

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

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

1 个答案:

答案 0 :(得分:4)

您在扫描循环中根本没有为变量分配数据,不仅仅是这样,而是从扫描器两次读取数据,而只检查一次 ,这是一件危险的事情。

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

我会:

  • 使用两个扫描程序变量,一个,fileScanner,读取文件中的每一行文字,...
  • 一个名为lineScanner的读取线上的每个标记。
  • 我使用外部while循环,检查fileScanner.hasNextLine(),然后调用nextLine()将行读入字符串,称为line
  • 然后我创建一个新的Scanner,其中创建了一行String,并将其分配给一个lineScanner变量。
  • 我使用内部while循环在lineScanner.hasNext()循环,并将数据读入您的变量。
  • 我会在外部循环结束时关闭内线扫描器,以免浪费资源。

或者,您可以使用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();
     }
  }