3

I'm trying to do encode/decode program and I'm encountering all kinds of Exceptions here!

problems that is popping up caused by multiple/single scanner/s:

  • InputMismatchException | NumberFormatException (ATTEMPT 2)

  • NoSuchElementException (ATTEMPT 3)

Before going through I would like to address that this is not a duplicate and I have looked up multiple problems on StackOverFlow of this kind and none helped me really much. Similiar problems that I've looked at: link1 link2

Note that the wished end results are like the results of the first attempt but with somehow better cleaner exception handling and closed scanners.

FIRST ATTEMPT

  • Now this program gives me the desired results but its a bad programming to have two scanners and one of them ( input method scanner ) is never closed:

    public static void main(String[] args) {
    Scanner sc=new Scanner (System.in);
    int choice = 0;
    do {
        System.out.println("This program to encode or decode a byte array " +
                "\n (o_O) Choices are: " +
                "\n 1: Press 1 to enter the encode mode" +
                "\n 2: Press 2 to enter the decode mode" +
                "\n 3: Press 3 to Exit!");
        try {
            //it has to be parseInt because if you used sc.nextInt() the program will go nuts even with try catch.
            choice=Integer.parseInt(sc.next());
            //choice=sc.nextInt();
            /*Question: why when i use this with the existing try catch i the program work for ever but when i use Integer.parseInt(sc.nextLine())
             * the program would normally ask for another value?
             */
        } catch (InputMismatchException | NumberFormatException e) {
            System.out.println("invalid type or format!");
        } catch (NoSuchElementException e) {
            System.out.println("no such");
            //break; if i uncomment this the programm will work For Ever
        }
        switch(choice){
    
        case 1 :
            System.out.println("entering the encode mode!");
            countAndEncode( input() );
            break;
        case 2 :
            countAndDecode( input() );
            break;
        case 3 :
            System.out.println("exiting...");
            break;
        default :
            System.out.println("please enter a valid option and valid format!");
        }
    
    } while (choice!=3);
    sc.close();
     }
    
     public static byte [] input() {
    //arrayList because we dont know the size of the array its like StringBuilder
    //ArrayList<Byte> inArray = new ArrayList<Byte>(); 
    //according to StackOverflow using ArrayList to store bytes is inefficient
    Scanner inScanner=new Scanner (System.in);
    
    ByteArrayOutputStream inArray= new ByteArrayOutputStream();
    
    System.out.println("enter a sequence of ints please! ");
    System.out.println("non-int will terminate the input!");
    
    while (inScanner.hasNext()) {
        byte i;
        try {
            i = inScanner.nextByte();
            inArray.write(i);
        } catch (InputMismatchException e) {
            System.out.println("input terminated!");
            break;
        }
    }
    //System.out.println(Arrays.toString(inArray.toByteArray()));
    //inScanner.close();
    return inArray.toByteArray();
     }
    

OUTPUT OF FIRST ATTEMPT:

This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are: 
 1: Press 1 to enter the encode mode
 2: Press 2 to enter the decode mode
 3: Press 3 to Exit!
 1
 entering the encode mode!
 enter a sequence of bytes please! 
 non-int will terminate the input!
 1
 1
 3
 e
 input terminated!
 [1, 1, 3]
 the encoded list is [-1, 1, 2, 3]
 This is a program to encode or decode bytes based on RLE ALgorithm
 (o_O) Choices are: 
 1: Press 1 to enter the encode mode
 2: Press 2 to enter the decode mode
 3: Press 3 to Exit!
 At it goes forever without errors.

SECOND ATTEMPT

so what i did after one fellow of you guys sugessted to take a look at this problem link is this:

Now i didnt close the input scanner and i gave the input method a scanner as a parameter:

public static void main(String[] args) {
    Scanner sc=new Scanner (System.in);
    int choice = 0;
    do {
        System.out.println("This is a program to encode or decode bytes based on RLE ALgorithm" +
                "\n (o_O) Choices are: " +
                "\n 1: Press 1 to enter the encode mode" +
                "\n 2: Press 2 to enter the decode mode" +
                "\n 3: Press 3 to Exit!");
        try {
            //it has to be parseInt because if you used sc.nextInt() the program will go nuts even with try catch.
            choice=Integer.parseInt(sc.next());
            //choice=sc.nextInt();
            /*Question: why when i use this with the existing try catch i the program work for ever but when i use Integer.parseInt(sc.nextLine())
             * the program would normally ask for another value?
             */
        } catch (InputMismatchException | NumberFormatException e) {
            System.out.println("invalid type or format!");
        } catch (NoSuchElementException e) {
            System.out.println("no such");//TODO SOLVE IT PLEASE ITS DRIVING ME CRAZYYYYYYYYYYY!!!!!!!
            break;
        }
        switch(choice){

        case 1 :
            System.out.println("entering the encode mode!");
            countAndEncode( input(sc) );
            break;
        case 2 :
            //countAndDecode( input(sc) );
            break;
        case 3 :
            System.out.println("exiting...");
            break;
        default :
            System.out.println("please enter a valid option and valid format!");
        }

    } while (choice!=3);
    sc.close();
}
/**
 * with this method user will be able to give the desired sequence of bytes. 
 * @return a byte array to be encoded.
 */
public static byte [] input(Scanner inScanner) {
    //arrayList because we dont know the size of the array its like StringBuilder
    //ArrayList<Byte> inArray = new ArrayList<Byte>(); 
    //according to StackOverflow using ArrayList to store bytes is inefficient
    //Scanner   inScanner=new Scanner (System.in);

    ByteArrayOutputStream inArray= new ByteArrayOutputStream();

    System.out.println("enter a sequence of bytes please! ");
    System.out.println("non-int will terminate the input!");

    while (inScanner.hasNext()) {//TODO THIS MIGHT BE THE REASON FOR THE above "SUCH"
        byte i;
        try {
            i = inScanner.nextByte();   
            inArray.write(i);   
        } catch (InputMismatchException e) {
            System.out.println("input terminated!");
            break;
        }
    }
    System.out.println(Arrays.toString(inArray.toByteArray()));
    //inScanner.close();  dont close it because it cant be re-opened
    return inArray.toByteArray();
}

Doing so doesn't give me the desired results at all:

  • After choosing one to encode and receive the encoded bytes I will get stuck forever in the encoding mode and the InputMismatchException | NumberFormatException clause will get activated so I cant get a chance to select a new input!

    This is a program to encode or decode bytes based on RLE ALgorithm (o_O) Choices are: 1: Press 1 to enter the encode mode 2: Press 2 to enter the decode mode 3: Press 3 to Exit! 1 entering the encode mode! enter a sequence of bytes please! non-int will terminate the input! 1 e input terminated! 1 the encoded list is 1 This is a program to encode or decode bytes based on RLE ALgorithm (o_O) Choices are: 1: Press 1 to enter the encode mode 2: Press 2 to enter the decode mode 3: Press 3 to Exit! invalid type or format! entering the encode mode! enter a sequence of bytes please! non-int will terminate the input!

  • NOTES:

  • 1.commenting sc.close() in main caused the exact same error as above..
  • 2.that moving scanner above main and declaing it as a global static variable did the exact thing as the faild above results.

THIRD ATTEMPT

now i left both of the closed each scanner and this activated the NoSuchElementException in main Take a look:

public static void main(String[] args) {
    Scanner sc=new Scanner (System.in);
    int choice = 0;
    do {
        System.out.println("This is a program to encode or decode bytes based on RLE ALgorithm" +
                "\n (o_O) Choices are: " +
                "\n 1: Press 1 to enter the encode mode" +
                "\n 2: Press 2 to enter the decode mode" +
                "\n 3: Press 3 to Exit!");
        try {
            //it has to be parseInt because if you used sc.nextInt() the program will go nuts even with try catch.
            choice=Integer.parseInt(sc.next());
            //choice=sc.nextInt();
            /*Question: why when i use this with the existing try catch i the program work for ever but when i use Integer.parseInt(sc.nextLine())
             * the program would normally ask for another value?
             */
        } catch (InputMismatchException | NumberFormatException e) {
            System.out.println("invalid type or format!");
        } catch (NoSuchElementException e) {
            System.out.println("no such");//TODO SOLVE IT PLEASE ITS DRIVING ME CRAZYYYYYYYYYYY!!!!!!!
            break;
        }
        switch(choice){

        case 1 :
            System.out.println("entering the encode mode!");
            countAndEncode( input() );
            break;
        case 2 :
            //countAndDecode( input() );
            break;
        case 3 :
            System.out.println("exiting...");
            break;
        default :
            System.out.println("please enter a valid option and valid format!");
        }

    } while (choice!=3);
    sc.close();
}
/**
 * with this method user will be able to give the desired sequence of bytes. 
 * @return a byte array to be encoded.
 * @throws IOException 
 */
public static byte [] input() {
    //arrayList because we dont know the size of the array its like StringBuilder
    //ArrayList<Byte> inArray = new ArrayList<Byte>(); 
    //according to StackOverflow using ArrayList to store bytes is inefficient
    Scanner inScanner=new Scanner (System.in);

    ByteArrayOutputStream inArray= new ByteArrayOutputStream();

    System.out.println("enter a sequence of bytes please! ");
    System.out.println("non-int will terminate the input!");

    while (inScanner.hasNext()) {//TODO THIS MIGHT BE THE REASON FOR THE above "SUCH"
        byte i;
        try {
            i = inScanner.nextByte();   
            inArray.write(i);   
        } catch (InputMismatchException e) {
            System.out.println("input terminated!");
            break;
        }
    }
    System.out.println(Arrays.toString(inArray.toByteArray()));
    inScanner.close(); 
    return inArray.toByteArray();
}

in this attempt i , at least, might know what is causing the NoSuchElementException to jump up and i think its because closing one scanner will close the input stream for the whole code.(correct me if im wrong!)

OUTPUT FOR THE THIRD ATTEMPT IS:

This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are: 
 1: Press 1 to enter the encode mode
 2: Press 2 to enter the decode mode
 3: Press 3 to Exit!
 1
 entering the encode mode!
 enter a sequence of bytes please! 
 non-int will terminate the input!
-1
-1
 e
 input terminated!
 [-1, -1]
 the encoded list is [-1, -1, -1, -1]
 This is a program to encode or decode bytes based on RLE ALgorithm
 (o_O) Choices are: 
 1: Press 1 to enter the encode mode
 2: Press 2 to enter the decode mode
 3: Press 3 to Exit!
no such

SOLUTION TO DISCUSS BY @Villat

First of all big thanks to you man for helping and investing time and effort. Now, i have small question regarding these lines:

 if(sc.hasNextInt()) choice=sc.nextInt();
            else {
                sc.next();
                continue;
            }
            error = false;
  • So let me see if i got this right, those lines play a role as a precaution,and please correct me if im wrong!, to prevent the Exception from popping up right.

So wouldnt it be enough to write the following ditching the try-catch blocks because NoSuchElementException has no chance to emerge and the InputMismatchException is being treated and prevented by the else block:

             while (error){
             if(sc.hasNextInt()) choice=sc.nextInt();
             else {
                 sc.next();
                 continue;
             }
             error = false;
             }

Just for training purpouses if i would like to Handle this error by try-catch block would you consider it clean and immune to Exceptions if i wrote it like this: (ditching the NumberFormatException)

-so Demonstrating the Handle variant of your answer would it be like this right?

                while (error){
                try {
                    choice=sc.nextInt();
                    error = false;                
                } catch (InputMismatchException /*| NumberFormatException*/ e) {
                    error = false;
                    //System.out.println("invalid type or format!");    
                    sc.next();
                    continue;
                }
            }
StudentAccount4
  • 186
  • 1
  • 11
  • Hey, in your 3rd attemp, your input is: -1, -1, e... and then you get all the messages included "no such"? Or your input is: -1, -1, e, X? (being X some other input) – Villat Oct 10 '19 at 19:10
  • thanks sir for trying to help but when giving input to the input method i explicitly did put try and catch with error to handle ``InputMismatchException`` but this is not the problem this will just terminate the input in the input method and my main problem is is in the third attempt when closing the input stream the ``NoSuchElementException`` catch gets activated in main somehow? – StudentAccount4 Oct 11 '19 at 14:09
  • I'm trying to understand the chars that you input in the 3rd attemp, are they -1, -1, e... or -1, -1, e, X (being X some other char)? – Villat Oct 11 '19 at 14:10
  • sir the input is of type byte and it will accept just numbers to save in bytes and in case any letter (e or X or whatever) will case the input to terminate. so the scanner will accept just numbers and anything else will cause the input to betermiated – StudentAccount4 Oct 11 '19 at 14:18
  • after giving anything but int the input stream will get terminated and the program shall work with that. so small example the -1,1,3,x (x being & $§""!"%/)= )will terminate the input no matter if its sign or letter. so as long as your input is number the input will not get terminated. – StudentAccount4 Oct 11 '19 at 14:26

1 Answers1

1

I made a few changes to your code (and removed comments to make it more readable). Basically, I'm only using one Scanner right now, and I'm not moving forward into the options until a sc.nextInt() appears.

public static void main(String[] args){
    Scanner sc=new Scanner (System.in);
    int choice = 0;
    do {
        System.out.println("This is a program to encode or decode bytes based on RLE ALgorithm" +
                "\n (o_O) Choices are: " +
                "\n 1: Press 1 to enter the encode mode" +
                "\n 2: Press 2 to enter the decode mode" +
                "\n 3: Press 3 to Exit!");
        boolean error = true;
        while (error){
            try {
                if(sc.hasNextInt()) choice=sc.nextInt();
                else {
                    sc.next();
                    continue;
                }
                error = false;
            } catch (InputMismatchException | NumberFormatException e) {
                System.out.println("invalid type or format!");
            } catch (NoSuchElementException e) {
                System.out.println("no such");
            }
        }
        switch(choice){

            case 1 :
                System.out.println("entering the encode mode!");
                System.out.println(input(sc));
                break;
            case 2 :
                //countAndDecode(input(sc));
                break;
            case 3 :
                System.out.println("exiting...");
                break;
            default :
                System.out.println("please enter a valid option and valid format!");
        }

    } while (choice!=3);
    sc.close();
}

Input method:

public static byte [] input(Scanner sc) {
    ByteArrayOutputStream inArray= new ByteArrayOutputStream();

    System.out.println("enter a sequence of bytes please! ");
    System.out.println("non-int will terminate the input!");

    while (sc.hasNext()) {
        byte i;
        try {
            i = sc.nextByte();
            inArray.write(i);
        } catch (InputMismatchException e) {
            System.out.println("input terminated!");
            break;
        }
    }
    System.out.println(Arrays.toString(inArray.toByteArray()));
    return inArray.toByteArray();
}
Villat
  • 1,455
  • 1
  • 16
  • 33
  • thanks man!. would you take a loot at the post again i added some point that i'd like to discuss with you ;) – StudentAccount4 Oct 12 '19 at 15:01
  • Hey @studentaccount4, it's better to handle all the exceptions, it gives you control over your code. It my answer was helpful, you can accept it and vote :) – Villat Oct 12 '19 at 22:36