java - 处理输入扫描器引起的异常

标签 java java.util.scanner numberformatexception nosuchelementexception inputmismatchexception

我正在尝试进行编码/解码程序,但在这里遇到了各种异常!

由多个/单个扫描仪/秒引起的问题:

  • 输入不匹配异常 | NumberFormatException (ATTEMPT 2)
  • NoSuchElementException(尝试 3)

  • 在开始之前,我想说明这不是重复的,我在 StackOverFlow 上查找了多个此类问题,但没有一个对我有太大帮助。
    我看过的类似问题:link1 link2

    请注意,希望的最终结果类似于第一次尝试的结果,但在某种程度上具有更好的更清晰的异常处理和封闭的扫描器。

    第一次尝试
  • 现在这个程序给了我想要的结果,但它有两个扫描仪是一个糟糕的编程,其中一个(输入法扫描仪)永远不会关闭:
    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();
     }
    

  • 第一次尝试的输出:
    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.
    

    第二次尝试

    所以在你们中的一个人建议看看这个问题之后我做了什么link这是:

    现在我没有关闭输入扫描仪,我给输入法一个扫描仪作为参数:
    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();
    }
    

    这样做根本没有给我想要的结果:
  • 选择一个编码并接收编码的字节后,我将永远卡在编码模式和 InputMismatchException | NumberFormatException 中。条款将被激活,所以我无法有机会选择新的输入!

    这是一个基于 RLE 算法对字节进行编码或解码的程序
    (o_O) 选项是:
    1:按1进入编码模式
    2:按2进入解码模式
    3:按3退出!
    1
    进入编码模式!
    请输入字节序列!
    非整数将终止输入!
    1
    电子
    输入终止!
    1
    编码列表为 1
    这是一个基于 RLE 算法对字节进行编码或解码的程序
    (o_O) 选项是:
    1:按1进入编码模式
    2:按2进入解码模式
    3:按3退出!
    无效的类型或格式!
    进入编码模式!
    请输入字节序列!
    非整数将终止输入!
  • 备注:
  • 1.评论sc.close()主要导致与上述完全相同的错误..
  • 2. 在 main 之上移动扫描仪并将其声明为全局静态变量与上述失败结果完全相同。

  • 第三次尝试

    现在我离开了关闭的每个扫描仪,这激活了 NoSuchElementException在主要看一下:
    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();
    }
    

    在这次尝试中,我至少可能知道是什么导致了 NoSuchElementException跳起来,我认为这是因为关闭一个扫描仪将关闭整个代码的输入流。(如果我错了,请纠正我!)

    第三次尝试的输出是:
    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
    

    由@Villat 讨论的解决方案

    首先非常感谢您的帮助和投入时间和精力。
    现在,我有关于这些行的小问题:
     if(sc.hasNextInt()) choice=sc.nextInt();
                else {
                    sc.next();
                    continue;
                }
                error = false;
    
  • 所以让我看看我是否做对了,这些行起到了预防作用,如果我错了,请纠正我!,以防止异常弹出正确。

  • 所以写下面的抛弃 try-catch 还不够吗?阻止是因为 NoSuchElementException没有机会出现和InputMismatchException正在被 else 块处理和阻止:
                 while (error){
                 if(sc.hasNextInt()) choice=sc.nextInt();
                 else {
                     sc.next();
                     continue;
                 }
                 error = false;
                 }
    

    如果我想通过 try-catch 处理此错误,仅用于培训目的如果我这样写,你会认为它干净并且不受异常影响:(放弃 NumberFormatException)

    -so 演示 Handle variant你的答案是这样吗?
                    while (error){
                    try {
                        choice=sc.nextInt();
                        error = false;                
                    } catch (InputMismatchException /*| NumberFormatException*/ e) {
                        error = false;
                        //System.out.println("invalid type or format!");    
                        sc.next();
                        continue;
                    }
                }
    

    最佳答案

    我对您的代码进行了一些更改(并删除了注释以使其更具可读性)。基本上,我只使用一个 Scanner现在,直到 sc.nextInt() 我才开始进入选项出现。

    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();
    }
    

    输入法:
    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();
    }
    

    关于java - 处理输入扫描器引起的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58328871/

    相关文章:

    java - 即使没有抛出异常,代码也会进入 catch block

    java - 在 Jenkinsfile 中使用 Publish Over SSH 时出现 NotSerializedException

    java - (Java) GUI NumberFormatException 捕获异常,但挂起窗口

    Java:如何将十六进制转换为整数?

    java - Android Fragment 意外错误

    java - 使用 RestTemplate 发送多部分文件

    java - 在文本文件上使用分隔符

    java - 当扫描模式时,如何在字符串中检查 float 范围?

    java - 如何让这段代码停止在非数字的地方?

    java - JTextField 值上的 NumberFormatException