簡體   English   中英

Java中的文件讀取和空指針異常

[英]Reading From File in Java and Null Pointer Exception

我對Java很陌生,遇到了一個我自己無法解決的問題。 我用谷歌搜索了異常,但據我所知,問題太具體了,所以我發現自己在這里。 這是我的問題。

我有一個名為Student的類,該類具有休閑的數據成員及其get / set方法:

private String studentNumber;
private String firstName;
private String lastName;
private int age;
private String gender;
private String country;

我創建了一個實例數組作為休假:

Student studentList[] = new Student(10);

我有一個數據庫(文本文件)

081935 Cengiz rrrrr Male 21 Turkey
082935 Ayşe aaaaa Female 22 England
083935 Onur bbbbb Male 23 Germany
084935 Fatma ccccc Female 24 Cyprus
085935 Ali dddd Male 21 China
086935 Zehra eeee Female 22 Denmark
087935 Murat ffff Male 25 France
088935 Selin ggggg Female 26 Japan
086935 Cengiz hhhh Male 20 Korea
080935 Damla qqqqqq Female 19 Iran

我想做的就是將所有這些信息都帶到我的類實例中,而我試圖做到這一點卻令人失望:

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

public class StudentTracker  {

    private static int counter = 0;
    private static Student studentList[];

    public static void readFromFile() throws FileNotFoundException {
        File file = new File("Database.txt");
        Scanner scanner = new Scanner(new FileReader(file));
        try {
              while (scanner.hasNextLine()){
                processLine(scanner.nextLine());
              }
        } finally {
            scanner.close();
        }
    }


    public static void processLine(String line) {
        Scanner scanner = new Scanner(line);
        scanner.useDelimiter(" ");
        if (scanner.hasNext()) {
          studentList[counter].setStudentNumber(scanner.next());
          studentList[counter].setFirstName(scanner.next());
          studentList[counter].setLastName(scanner.next());
          studentList[counter].setGender(scanner.next());
          studentList[counter].setAge(Integer.parseInt(scanner.next()));
          studentList[counter].setCountry(scanner.next());      
          counter++;
        }
        else {
            System.out.println("Empty or invalid line. Unable to process.");
        }
      }

    public static void main(String[] args) throws FileNotFoundException {

        studentList = new Student[10];
        readFromFile();
        for(int i = 0; i < 10; i++) {
            System.out.printf(studentList[i].getStudentNumber(), " ",
                              studentList[i].getFirstName());

        }

    }

}

但它會產生令人討厭的錯誤:

Exception in thread "main" java.lang.NullPointerException
    at StudentTracker.processLine(StudentTracker.java:28)
    at StudentTracker.readFromFile(StudentTracker.java:16)
    at StudentTracker.main(StudentTracker.java:68)

順便說一句,找不到像C-scanf這樣的函數,該函數直到第一個空格之前都會獲取輸入,所以我找到了另一種方法來解析

readFromFile()和processLine函數,但是我不確定它們是否按預期工作。

先感謝您

這行:

studentList = new Student[10];

創建一個由10個元素組成的數組。 每個元素的值都不是Student 對象 ; 它是一個引用 -該引用將為null或對Student對象(或兼容類型)的引用。 每個元素都有一個空值開頭。

那條線不會創建任何Student對象

您需要先設置Student的實例,然后再設置其屬性,例如

if (scanner.hasNext()) {
  studentList[counter] = new Student();
  studentList[counter].setStudentNumber(scanner.next());
  ...

要么:

if (scanner.hasNext()) {
  Student student = new Student();
  student.setStudentNumber(scanner.next());
  ... fill in the other properties ...
  studentList[counter] = student;
  ...

作為附帶說明,此行:

private static Student studentList[];

...不是慣用的聲明。 這是有效的,但是大多數Java程序員都希望看到:

private static Student[] studentList;

這樣,所有類型信息都保存在一個地方。 (我也建議改用List<Student> ,並將其傳遞到方法中,而不要使用靜態變量,但不要讓自己超前...)

除了不初始化studentList的元素studentList ,這里

    if (scanner.hasNext()) {
      studentList[counter].setStudentNumber(scanner.next());
      studentList[counter].setFirstName(scanner.next());
      studentList[counter].setLastName(scanner.next());
      studentList[counter].setGender(scanner.next());
      studentList[counter].setAge(Integer.parseInt(scanner.next()));
      studentList[counter].setCountry(scanner.next());      
      counter++;
    }

您只檢查一次scanner.hasNext() ,然后多次調用scanner.next() 如果任何非空輸入行的元素少於預期的數量,則將拋出NoSuchElementException

OTOH在每個字段分配之前檢查hasNext()非常尷尬。 另一種選擇是使用String.split 這將產生一個String[] ,您可以在嘗試初始化新的Student對象之前檢查其長度以確保所有字段都存在。

您創建了一個Student數組,但從未在其中放置任何Student對象。

不用將它們設置為數組索引值,而是創建一個新對象,設置其屬性,然后將其分配給數組索引。

for( ... ) {
 Student x= new Student();
 x.set...
 studentList[index]= x;
}

在您的processLine中,您引用的是StudentList [counter],但從未將新的Student放入studentList [counter]中,因此您嘗試將setStudentName調用為null。 您應該將一個新學生放入庫珀的studentList中,然后使用它,或者使其更具可讀性,請執行以下操作

Student = new Student();
student.setThis( scanner.next());
student.setThat( scanner.next());
studentList[counter] = student;

您應該粘貼第28行的內容,以獲取異常。 需要檢查的幾件事:

  1. studentList[counter]是否為空?

  2. 在檢查scanner.hasNext()true您要多次調用scanner.next() 這些調用之一可以返回null嗎? 這在這里不能成為根本原因,因為異常會在堆棧上至少包含一個以上的方法,但是您仍然可能需要在代碼中進行檢查。

Student studentList[] = new Student(10);

您只是在創建一個大小為10的Student類型的數組。此數組包含10個Student引用,每個引用尚未定義(它將為null)。

在調用學生參考上的任何set方法之前,請實例化該對象

studentList[counter] = new Student();

所以你的代碼可能會變得像

if (scanner.hasNext()) {
        studentList[counter] = new Student();
        studentList[counter].setStudentNumber(scanner.next());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM