Whats wrong with InputStreamReader here?

531 views Asked by At

I have created a Java Shopping Cart App. I have used InputStreamReader class for it. But its showing strange behavoiur. I have already tried Scanner class and Data Input Stream class. But they they do not seem to be fit for this app.

Can anyone please point out whats wrong with this class?

Also as already stated, Scanner class and DIS class tend to skip the user input, same as here while using ISR class ( see Output : Rate ). I am tired of trying every Java user input utility class, and modifying my code again and again.

import java.util.ArrayList;
//import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.Scanner;
import java.io.DataInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.lang.Throwable;


public class NewShop {


protected ArrayList<NewItem> ItemList;
ArrayList<NewItem> cartList ;

   // public DataInputStream dis = new DataInputStream(System.in);
   // private Scanner sc = new Scanner(System.in);
  private InputStreamReader isr = new InputStreamReader(System.in);

 public void addItem() {

    long aCode = 0;
    String aName ="";
    double aRate = 0;
    int aQuantity = 0;
    NewItem foundItem;

    System.out.println("Enter Item code:");
   /* try{
    String adddisString = dis.readLine();}
      catch(IOException e){e.printStackTrace();} */

    try{
    aCode = isr.read();
      System.out.println("code entered is : " + aCode);
       }
         catch(IOException e){e.printStackTrace();}

    foundItem = search(aCode);
    if (foundItem == null) {
        System.out.println("Item name : ");
        try{
        aName = dis.readLine();
          }
             catch(IOException e){e.printStackTrace();}
        System.out.println("Rate : "); 
        try{ aRate = isr.read(); }
           catch(IOException e){e.printStackTrace();}

        System.out.println("Quantity : ");
        try{aQuantity = isr.read();}
        catch(IOException e){e.printStackTrace();}


                  NewItem aItem = new NewItem(aName, aRate, aCode, aQuantity);
                  ItemList.add(aItem);
                  }
                  else {
                  System.out.println("Item exists");
                  }


  } 

}

Output :

shachindratripathi@saurabh-OptiPlex-3010:~/NewJava$ java NewShoppingCart
  New Shop for Items created.
  -----ITEM------
1. Display all items
2. Search items
3. Add items to list
4. Add items to cart
5. Issue item
6. Exit
Choice:
3
Enter Item code:
1
code entered is : 49
Item name : 
apple
Rate : 
Quantity : 
30
1. Display all items
2. Search items
3. Add items to list
4. Add items to cart
5. Issue item
6. Exit
Choice:
1
       code           name           rate          quantity 

        49            apple           10.0           51

                              ************ 
1. Display all items
2. Search items
3. Add items to list
4. Add items to cart
5. Issue item
6. Exit
Choice:
3

There are 3 answers

3
AxelH On BEST ANSWER

InputStreamReader allow you to read a Stream character per character using read that give you a int.

That int is not the value you a thinking of, it is a char representation of a number, so

'0' = 48
'1' = 49
...

More in this ASCII table

What you probably want to use here is a Scanner which is more simple in your case or a BufferedReader that give you the possibility to get the full line in a String.

Scanner sc = new Scanner(System.in);
int i = sc.nextInt(); //This will get the next number an parse it in an integer (or throw an exception)
//careful, the <ENTER> is still in the buffer, flush with sc.nextLine(); if needed
sc.close();

The reason you got some inputs skipped using Scanner is above, when you read a specific type (like readInt), the "enter" key is not read, so it remains in the buffer, the next call of nextLine will read it. You need to clear that input before you can get the correct value.

int i = sc.nextInt(); 
sc.nextLine(); //clear <enter>
String s = sc.nextLine(); //next input
5
TheRealHypo On

You do:

aCode = isr.read();

which returns you an Int Value (See Ascii-Table) of the first character you put in. So for the "1" you put in, you'll get the Ascii Code of "1", which is 49.

If you want to read Strings with InputStreamReader it can be done like this:

InputStreamReader isr = new InputStreamReader(System.in)
int c;
String input = "";
while((c = isr.read()) != -1){
        input+= (char) c;
}

But you would get better and easier results if you use a Scanner for this kind of stuff, see @AxelH answer for this.

2
Usagi Miyamoto On

If you use Readers you have to convert any non-string value yourself. DataInputs uses binary format, not suitable for user input.

Thus your easiest solution would be Scanner, so try something like this:

public class NewShop
{
  protected ArrayList<NewItem> ItemList;
  ArrayList<NewItem> cartList ;
  private Scanner in = new Scanner(System.in);
  public void addItem()
  {
    long aCode = 0;
    String aName ="";
    double aRate = 0;
    int aQuantity = 0;
    NewItem foundItem;
    System.out.println("Enter Item code:");
    try
    {
      aCode = in.nextLong(); // this reads the to the first char that is not part of the 
      in.nextLine();         // long value, so we need to read till the end of the line...
      System.out.println("code entered is : " + aCode);
      foundItem = search(aCode);
      if (foundItem == null)
      {
        System.out.println("Item name : ");
        aName = in.nextLine();
        System.out.println("Rate : "); 
        aRate = in.nextDouble();
        in.nextLine();
        System.out.println("Quantity : ");
        aQuantity = in.nextInt();
        in.nextLine();
        NewItem aItem = new NewItem(aName, aRate, aCode, aQuantity);
        ItemList.add(aItem);
      }
      else
      {
        System.out.println("Item exists");
      }
    }
    catch(IOException e)
    {
      e.printStackTrace();
    }
  } 
}

Also removed the inner try-catches as if any value is wrong, it is not going to work later...