Search code examples
javabufferedreaderfilereaderinventory

Inventory program only reads one line?


So I've been having trouble with this program for a long time now. The assignment wants me to read a .txt file using BufferedReader, FileReader and StringTokenizer, create an array, then print all the information. I went to my professor for help and she hashed out a skeleton for me, but after some editing this is what I've come up with:

import java.io.*;
import java.util.StringTokenizer;

public class Inventory {

    public static void main(String[] args) throws IOException {
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        final int MAX = 500;
        InventoryItem[] items = new InventoryItem[MAX];
        StringTokenizer tokenizer;
        String line, name, file = "inventory.txt";
        int price, units, count = 0;

        try {
            FileReader fr = new FileReader(file);
            BufferedReader inFile = new BufferedReader(fr);
            line = inFile.readLine();

            while ((line = inFile.readLine()) != null) {
                tokenizer = new StringTokenizer(line);

                while (tokenizer.hasMoreElements()) {
                    name = tokenizer.nextToken();

                    try {
                        units = Integer.parseInt(tokenizer.nextToken());
                        price = Integer.parseInt(tokenizer.nextToken());
                        items[count++] = new InventoryItem(name, units, price);

                    } catch (NumberFormatException exception) {
                        System.out.println("Error in input. Line ignored:");
                        System.out.println(line);
                    }
                    line = inFile.readLine();
                }
            }

            inFile.close();
            for (int scan = 0; scan < count; scan++)
                System.out.println(items[scan]);
        } catch (FileNotFoundException exception) {
            System.out.println("The file " + file + " was not found.");
        } catch (IOException exception) {
            System.out.println(exception);
        }
        stdin.read();
    }
}

The program compiles with no issue, but when I run it it prints out the exception error line "Error in input. Line ignored", then prints out the second line in my .txt file, then doesn't read the next line and stays in the run.

Even after this the assignment wants me to output the data in a certain way, which I don't know how to do without System.out.println.

Here is the InventoryItem code:

 import java.util.*;
 import javax.swing.*;
 import java.text.DecimalFormat;

 public class InventoryItem
{
   public static String name;
   private int units;
   private double price;

   /**
    * Default Constructor
    */
   public InventoryItem()
   {
   this (name, 3, 20.00);
   }
   /**
    * Non-Default Constructor
    * Constructs new InventoryItem class with parameters name, units
    * and price from main class. 
    * 
    * @param name   name of item
    * @param units  number of units
    * @param price  price of item
    */
   public InventoryItem (String name, int units, double price)
   {
   this.name = name;
   this.units = units;
   this.price = price;
   }
   /**
    * Returns the name
    * 
    * @return returns name of item
    */
   public String getName()
    {
   return name;
   }
   /**
    * Sets the name
    *
    * @param name The name of the unit
    */
   public void setName(String name)
   {
   this.name = name;
   }
   /**
    * Returns the number of units
    *
    * @return returns the number of units
    */
   public int getUnits()
   {
   return units;
   }
   /**
    * Sets the number of units
    *
    * @param units the number of units
    */
   public void setUnits(int units)
   {
   this.units = units;
   }
   /**
    * Returns the price of each unit
    *
    * @return returns the price
    */
    public double getPrice()
   {
   return price;
   }
   /**
    * Sets the price
    *
    * @param price the price of each unit
    */
   public void setPrice(double price)
   {
   this.price = price;
   }
   /**
    * Returns the data in the form of an array
    *
    * @param name the name of the unit
    * @param units the number of units
    * @param price the price of each unit
    * @return Returns the inputted data in a specified format
    */
    public String toString()
   {
   DecimalFormat fmt = new DecimalFormat("0.00");

   return name + ":\t" + units + "\t" + price + "\t" +
   fmt.format((units * price));
   }

}

Solution

  • You have made two errors.

    Prices contain decimals, so you can't use int. float is one possibility (although, in general, not recommended):

    float price;
    //...
          price = Float.parseFloat(tokenizer.nextToken());
    

    The second error is reading each line twice. The following change avoids this:

       line = inFile.readLine();     
       while( line != null ) {
           //...
           line = inFile.readLine();
       }
    

    Note that you can simplify this:

       while( (line = inFile.readLine()) != null {
           //...
       }
    

    To print you items, write a suitable method public String toString() in your InventoryItem class.

    Later

    The code for InventoryItem must be fixed:

     public class InventoryItem {
         private String name = "";
         private int units;
         private double price;
    
         public InventoryItem(){
         }
    
         public InventoryItem (String name, int units, double price){
             this.name = name;
             this.units = units;
             this.price = price;
         }
         // ... etc
    }
    

    There is really no point in providing fancy values for an object created with the default constructor. Assigning the empty string "" to name is reasonable to avoid NPE; int and double fields are best left at 0.

    Alternatively, simply remove the default constructor.