Search code examples
javaserializationnullpointerexceptionsymbolsjgrasp

NullPointerException in Serializable object


This is a college course assignment that creates a ItemRecord class and implements Serializable with getter and setters, then overrides the toString method. Next I created a ItemRecordReport class with a Scanner object mapped to an input file "ItemRecord_text.txt". Created an ObjectOutputStream object mapped to a binary output file "ItemRecord_binary.txt". Created an ObjectInputStream object mapped to the binary file. Everything works. I modified this post by putting in an array in method main and changing the field values with a additional text document. My error is a NullPointerException: This is the stack trace

Item   Cost     Quantity  Description
Number
A100  $ 99.99   10        Canon PowerShot-135
A200  $149.99   50        Panasonic-Lumix T55
A300  $349.99   20        Nikon- D3200 DSRL
A400  $280.99   30        Sony- DSC-W800
A500  $ 97.99   20        Samsung- WB35F
Exception in thread "main" java.lang.NullPointerException
at ItemRecordReport.endRecord(ItemRecordReport.java:165)
at ItemRecordReport.main(ItemRecordReport.java:156)

 ----jGRASP wedge2: exit code for process is 1.
 ----jGRASP: operation complete.

//create program so that objects of class can be serialized, implements interface Serialiable //create constructor with 4 parameters with accompanying get and set methods, Override toString method //create text file with 5 records, create Scanner object,ObjectOutputStream, and ObjectInputStream //create new ItemRecord object, change values of all fields in ItemRecord object using object's set methods //modify ItemRecord object using toString method

 import java.io.Serializable;
 public class ItemRecord implements Serializable

 {  //declare 4 fields with private access
 private String itemNumber;
 private double cost;
 private int quantity;
 private String description;


 //constructor with no arguments call other constructor with default values
 public ItemRecord()
 {
 this("",0.0,0,"");

 }//end constructor with no arguments
//constructor with 4 arguments
public ItemRecord(String number, double price, int quant, String desc)
{
  setItemNumber(number);
  setCost(price);
  setQuantity(quant);
  setDescription(desc);
 }//end constructor

 public void setItemNumber(String number)
 {
  itemNumber = number;
 }//end setItemNumber
 public String getItemNumber()
 {
  return itemNumber;
 }//end getItemNumber

 public void setCost(double price)
{
  cost = price;
}//end seCost
public double getCost()
{
  return cost;
}//end getCost

public void setQuantity(int quant)
{
  quantity = quant;
}//end setQuantity
public int getQuantity()
{
  return quantity;
}//end getQuantity

public void setDescription(String desc)
{
  description = desc;
}//end setDescription
public String getDescription()
{
  return description;
}//end getDescription
public static void printHeading()
{
System.out.println("Item   Cost     Quantity  Description");
System.out.print("Number");
System.out.println();
}

public String toString()
{
 return this.getItemNumber()+String.format("  $%6.2f   ",+this.getCost())+String.format("%4d       ",+this.getQuantity())+this.getDescription();
}
}//end class ItemRecord

Here is the other test class: This class contain the ObjectOutputStream and ObjectInputStream objects. Therefore method main is here as well as the ItemRecordReport object that I use to call the methods in main.

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

public class ItemRecordReport
{  private ObjectOutputStream output;//writes to binary 
private ObjectInputStream binInFile;//reads binary
private Scanner input;

public void openInputBinaryFile()
 {//create a ObjectInputStream object that will read a binary file
  try
  {
    binInFile  = new ObjectInputStream(new FileInputStream("ItemRecord_binary.txt"));

  }//end try
  catch (IOException ioException)
  {
     System.out.println("Error opening file.");
  }//end catch 
  }//end openInputBinaryFile

  public void openOutputBinaryFile()
  {  
 //creating a binary objectOutputStream text file
  try
  {
     output = new ObjectOutputStream(
     new FileOutputStream("ItemRecord_binary.txt"));
   }//end try
   catch (IOException ioException)
   {
     System.err.println("Error opening file");
  }

  }//end openOutputBinaryFile
  public void readInputTextRecords()
  {
     ItemRecord record;
     String itemNumber;
     double cost;
     int quantity;
     String description;


     try
     {
       input  = new Scanner(new File("ItemRecord_text.txt"));
     }

      catch (IOException e)
     {
        System.out.println("Error file not found");
     }//end catch

      while(input.hasNext())
        {
        try{
              itemNumber = input.next();
              cost = input.nextDouble();
              quantity = input.nextInt();
              description = input.nextLine();

              record = new ItemRecord(itemNumber,cost,quantity,description);

              //writing into the binary text file
              output.writeObject(record);
           }

           catch (IOException ioException)
           {
              System.out.println("Error writing to binary file.");
              return;
           }
        }  
    }//end readInputRecords

   public void readInputBinaryRecords()
   {
     openInputBinaryFile();
     ItemRecord otherRecord;

     try
     {   while (true)
        {
           otherRecord = (ItemRecord) binInFile.readObject(); //use down cast
           System.out.println(otherRecord.toString());
        }
     }
      catch (EOFException e)
     {
        return;
     }//end catch
      catch (ClassNotFoundException e)
     {
        System.err.println("Unable to create object.");
     }//end catch 
     catch (IOException ioException)
     {
        System.err.println("Error reading from binary file.");
     }//end catch 

   }//readInputBinaryRecords
   public void closeBinaryOutputFile()
  {
  try
  {  if (output !=null )
        output.close();
  }//end try
  catch ( IOException ioException)
  {
     System.out.println( "Error closing file");
     System.exit(1);
  }//end catch
   }//end closeBinaryOutputFile

  public void closeBinaryInputFile()
 {
  try
  {  if (binInFile != null )
        binInFile.close();
     else
        System.out.println("No records were written to the binary file!");
  }//end try
  catch ( IOException ioException)
  {
     System.out.println( "Error closing file");
     System.exit(1);
  }//end catch
  }//end closeBinaryFile

 public static void main(String[] args)
{
 ItemRecordReport object = new ItemRecordReport();

 ItemRecord.printHeading();//print heading
 object.openOutputBinaryFile();//opens the binary file
 object.readInputTextRecords();//reads text file and writes to binary file
 object.closeBinaryOutputFile();//closes the binaryOutputFile

 object.openInputBinaryFile();//opens binary file
 object.readInputBinaryRecords();
 object.closeBinaryInputFile();
 Scanner inFile;
 ItemRecord[] itemRecord = new ItemRecord[5];


  itemRecord[x] = new ItemRecord();


  for (int x = 0; x <= 4; x++){
     itemRecord[x].setItemNumber("");
     itemRecord[x].setCost(0);
     itemRecord[x].setQuantity(0);
     itemRecord[x].setDescription("");
  }

  try
  {
     inFile = new Scanner(new File("itemRecord.txt"));

     while(inFile.hasNext())
      {
      for(int count =0; count<=4; count++)
        {
          itemRecord[count].setItemNumber(inFile.next());
          itemRecord[count].setCost(inFile.nextDouble());
          itemRecord[count].setQuantity(inFile.nextInt());
          itemRecord[count].setDescription(inFile.next());

     }//end for loop 
   }//end while

  }
  catch (IOException e)
  {
     System.out.println("Error file not found");
  }//end catch
  try
  {
  ObjectOutputStream binOutFile = new ObjectOutputStream
  (new FileOutputStream("ItemRecord_binary.txt"));
  }//end try
  catch (IOException e)
  {
  System.err.println("error opening file");
  }
  System.out.println(itemRecord.toString());



 }//end method main 



}//end class ItemRecordReport

And here is the text file:

A100 99.99 10 Canon PowerShot-135
A200 149.99 50 Panasonic-Lumix T55
A300 349.99 20 Nikon- D3200 DSRL
A400 280.99 30 Sony- DSC-W800
A500 97.99 20 Samsung- WB35F

This is the new text file to change the field values:

B100 98.00 10 ABC1010
B200 97.00 15 DEF1020
B300 96.00 10 GHI1030
B400 95.00 05 JKL1040
B500 94.00 01 MNO1050

Error stack trace
Item   Cost     Quantity  Description
Number
A100  $ 99.99   10        Canon PowerShot-135
A200  $149.99   50        Panasonic-Lumix T55
A300  $349.99   20        Nikon- D3200 DSRL
A400  $280.99   30        Sony- DSC-W800
A500  $ 97.99   20        Samsung- WB35F
Exception in thread "main" java.lang.NullPointerException
at ItemRecordReport.endRecord(ItemRecordReport.java:165)
at ItemRecordReport.main(ItemRecordReport.java:156)

 ----jGRASP wedge2: exit code for process is 1.
 ----jGRASP: operation complete.

Solution

  • There are numerous problems here. The NullPointerException comes from the fact that you've initialized the ItemRecord[] array but not any of its elements. You need to add

    itemRecord[x] = new ItemRecord();
    

    above line 153.

    However there are other problems.

    • You are making up your own error messages instead of printing the much more useful exception messages themselves, or, as you are still debugging, printing the stack trace. For example:

      catch (IOException ioException)
      {
          ioException.printStackTrace();
      }
      
    • You are catching exceptions and proceeding as though they didn't happen. Code that depends on the success of code in a try block should be inside the same try block. For example:

      try
      {
          input = new Scanner(new File("ItemRecord_text.txt"));
      }
      catch (IOException e)
      {
          e.printStackTrace();
      }//end catch
      while (input.hasNext())
      // ...
      

      should be

      try
      {
          input = new Scanner(new File("ItemRecord_text.txt"));
          while (input.hasNext())
          // ...
      }
      catch (IOException e)
      {
          e.printStackTrace();
      }//end catch
      
    • You aren't scanning the "ItemRecord.txt" file correctly. It has five columns but you're only scanning four of them. Left as an exercise for the reader.

    • I suggest you get out of the habit of writing

      } // end catch
      

      etcetera. Modern IDEs and proper indentation make this completley unnecessary, and it actually gets in the way in practice and they can often end up wrong. You've probably been taught it in school, and you should certainly do whatever you have to do to get the grades you want, but out here people don't do it much. Haven't seen it for decades.