`NullPointerException` thrown while searching text

2019-09-24 21:28发布

问题:

First, I keep getting a NullPointerException on the line I put in ** below. Second, my program is giving the wrong output (I somehow got it to work but then it went back to error). It must be a logic error. I have a file directory.txt of 11 lines, each with a name on it. When I run my program to try to find a certain name, it only finds the first name on the first line and everything else, it can't find. How can I fix these 2 errors?

I have 2 classes. This is the first class Directory:

import java.util.*;
import java.io.*;
public class Directory {
   //public static void main(String[] args) {
   final int maxDirectorySize = 1024;
   String directory[] = new String[maxDirectorySize];
   int directorySize = 0;
   File directoryFile = null;
   Scanner directoryDataIn = null;

   public Directory(String directoryFileName) {
      directoryFile = new File(directoryFileName);
      try {
         directoryDataIn = new Scanner(directoryFile);
      }
      catch (FileNotFoundException e) {
         System.out.println("File is not found, exiting!" + directoryFileName);
         System.exit(0);
      }
      while (directoryDataIn.hasNext()) {
         directory[directorySize++] = directoryDataIn.nextLine();
      }
   }
   public boolean inDirectory(String name) {
      boolean inDir = true;
      for (int i = 0; i < directory.length; i++) {
         **if (directory[i].equalsIgnoreCase(name))** 
            inDir = true;
         else 
            inDir = false;
      }
      return inDir;
   }
   public boolean add(String name) {
      if (directory.length == 1024)
         return false;
      for (int i = 0; i < directory.length; i++) {
         if (directory[i].equalsIgnoreCase(name))
            return false;
         else
            directory[directorySize++] = name;
            return true;
      }
      return false;
   }          

   public boolean delete(String name) {
      for (int i = 0; i < directory.length; i++) {
         if (directory[i].equalsIgnoreCase(name)) {
            directory[i] = null;
            return true;
         }   
         else
            return false;
      }
      return false;
   }

   public void closeDirectory() {
      directoryDataIn.close();
      PrintStream directoryDataOut = null;
      try {
          directoryDataOut = new PrintStream(directoryFile);
      }
      catch (FileNotFoundException e) {
         System.out.printf("File %s not found, exiting!", directoryFile);
         System.exit(0);
      }
      String originalDirectory[] = {"Mike","Jim","Barry","Cristian","Vincent","Chengjun","susan","ng","serena"};
      if (originalDirectory == directory)
         System.exit(0);
      else
         for (int i = 0; i < directorySize; i++)
            directoryDataOut.println(directory[i]);
         directoryDataOut.close();
   }
}

AND this is my second class which I'm trying to run but I keep getting exception main thread NullPointerException.

import java.io.*;
import java.util.*;
public class DirectoryWithObjectDesign {
   public static void main(String[] args) throws IOException {
   String directoryDataFile  = "Directory.txt";
   Directory d = new Directory(directoryDataFile);
   Scanner stdin = new Scanner(System.in);
   System.out.println("Directory Server is Ready!");
   System.out.println("Format: command name");
   System.out.println("Enter ^Z to end");
   while (stdin.hasNext()) {
      String command = stdin.next();
      String name = stdin.next();
      if (command.equalsIgnoreCase("find")) {
         if (d.inDirectory(name))
            System.out.println(name + " is in the directory");
         else 
            System.out.println(name + " is NOT in the directory");
      }
      else if (command.equalsIgnoreCase("add")) {
         if (d.add(name))
            System.out.println(name + " added");
         else 
            System.out.println(name + " cannot add! " + "no more space or already in directory");
      }
      else if (command.equalsIgnoreCase("delete")) {
         if (d.delete(name))
            System.out.println(name + " deleted");
         else
            System.out.println(name + " NOT in directory");
      }
      else {
         System.out.println("bad command, try again");
      }
   }
   }
}   

回答1:

This code:

  while (directoryDataIn.hasNext()) {
     directory[directorySize++] = directoryDataIn.nextLine();
  }

will only fill up as much of directory as there are lines in the input file (11 according to your question).

This code:

  for (int i = 0; i < directory.length; i++) {
     **if (directory[i].equalsIgnoreCase(name))** 

will loop over every entry in directory, up to its length (1024).

Since 1013 of those entries are null, trying to run equalsIgnoreCase() on them will result in a NPE.

Edit

You can solve this one of several ways. For instance, you could

  • keep track of the number of lines you read, and only read up to that point
  • check each entry to see if it is null before evaluating it
  • use a dynamically sized data structure instead of an array, such as ArrayList
  • perform the check on the known value (e.g. if (name.equalsIgnoreCase(directory[i])))
  • etc.


回答2:

Change

for (int i = 0; i < directory.length; i++) {

To

for (int i = 0; i < directorySize; i++ ){

directorySize is already Keeping track of the number of entries so any array entries above that will be null. Therefore trying to call equalsIgnoreCase() on them will get a NPE.

Actually this looks like a prime use for ArrayList rather than array. The list will expand as you need it and List.size() will give you the correct length.