是否可以将try与资源以及输入流一起使用? [英] Is it possible to use try with resources along with an input stream?

查看:79
本文介绍了是否可以将try与资源以及输入流一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用资源实现try时,我通过try语句()中的Scanner sc = new Scanner(System.in)创建一个Scanner对象. 在try块中,我提示用户输入一个数值,通过sc.nextLine()读取它,并利用parseDouble将其转换为方法. 如果最初输入的值无效,我会利用do-while循环再次提示用户输入值.

When implementing try with resources I am creating a Scanner object via Scanner sc = new Scanner(System.in) within () of the try statement. In the try block, I am prompting the user to enter a numeric value, reading it via sc.nextLine() and utilizing parseDouble to convert it to a method. I utilize a do-while loop to re-prompt the user to enter a value if an invalid value was entered initially.

但是,如果用户输入一个无效值,则会关闭输入流,并捕获NumberFormatException,但是在do-while循环的第二次迭代期间,将抛出找不到行" NoSuchElementException,并且由于'流关闭'java.io.IOException. 在尝试使用资源时是否有办法避免这种情况?

However, if the user enters an invalid value, the input stream closes, NumberFormatException is caught but during the second iteration of the do-while loop, a 'No line found' NoSuchElementException is thrown and infinitely thereafter due to the 'stream closed' java.io.IOException. Is there a way to circumvent this while utilizing try with resources?

public static void main(String[] args) {

  int x = 1;

  do {
      try (Scanner sc = new Scanner(System.in)) {
          System.out.print("Enter a numeric value: ");
          String input1 = sc.nextLine();
          Double d1;
          d1 = Double.parseDouble(input1);
          System.out.print("Enter a numeric value: ");
          String input2 = sc.nextLine();
          Double d2;
          d2 = Double.parseDouble(input2); 
          System.out.print("Choose an operation (+ - * /): ");
          String input3 = sc.nextLine();
          //sc.close();

          switch (input3) {
              case "+":
                  Double result = d1 + d2;
                  System.out.println("The answer is " + result);
                  break;
              case "-":
                  Double result1 = d1 - d2;
                  System.out.println("The answer is " + result1);
                  break;
              case "*":
                  Double result2 = d1 * d2;
                  System.out.println("The answer is " + result2);
                  break; 
              case "/":
                  Double result3 = d1 / d2;
                  System.out.println("The answer is " + result3);
                  break;
              default:
                  System.out.println("Unrecognized Operation!");
                  break;
          }
          x++;        
      } 
      catch (NumberFormatException e){ 
          System.out.println("Number formatting exception "+e.getMessage());
          System.out.println("Enter a proper value");    
      }
      catch (Exception e1){
          System.out.println("Arbitrary error encountered"+e1.getMessage());
      }
  }
  while(x==1);

}

推荐答案

正如其他人在评论中已经说过的那样,您不应将try-with-resource与未打开自己的资源一起使用,尤其是不要与System.in,它永远不能被应用程序关闭.

As already said by others in the comments, you shouldn’t use try-with-resource with a resource you didn’t open yourself, especially not with System.in, which should never be closed by an application.

除此之外,您应该更喜欢预先测试条件,而不是捕获异常.此外,尝试避免代码重复,您将得到一个更简单的解决方案:

Besides that, you should prefer testing conditions beforehand, instead of catching exceptions. Further, try to avoid code duplication and you’ll end up at a much simpler solution:

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in).useDelimiter("\\R");
    System.out.print("Enter first numeric value: ");
    double d1 = getDouble(sc);
    System.out.print("Enter second numeric value: ");
    double d2 = getDouble(sc);
    System.out.print("Choose an operation (+ - * /): ");
    while(!sc.hasNext("[-+*/]")) {
      System.out.println(sc.next()+" is not a valid operation");
    }
    String operation = sc.next();

    double result;
    switch (operation) {
        case "+": result = d1 + d2; break;
        case "-": result = d1 - d2; break;
        case "*": result = d1 * d2; break; 
        case "/": result = d1 / d2; break;
        default:
            throw new AssertionError("should not happen due to pretest");
    }
    System.out.println(d1+operation+d2);
    System.out.println("The answer is " + result);
}    
private static double getDouble(Scanner sc) {
    while(!sc.hasNextDouble()) {
        System.out.println(sc.next()+" is not a number");
    }
    return sc.nextDouble();
}

此解决方案使用hasNextDouble()来询问扫描程序下一个令牌是否具有双精度格式,只有在得到确认后,应用程序才会通过nextDouble()来获取它.否则,它将使用next()来获取无效的令牌,该令牌既可以提供报告,也可以将其从未处理的输入中删除.同样,hasNext("[-+*/]")检查输入是否与支持的四个运算符之一匹配.

This solution uses hasNextDouble() to ask the scanner whether the next token has a double format and only if that’s acknowledged, the application will fetch it via nextDouble(). Otherwise, it uses next() to fetch the invalid token, which serves both, reporting and removing it from the unprocessed input. Likewise, hasNext("[-+*/]") checks whether the input matches one the the supported four operators.

由于编译器不了解现在只有四个有效输入之一可能出现,因此我们必须在switchdefault情况下添加一个throwing语句,否则编译器会说可能尚未初始化.我们可以将result初始化为默认值,但是如果程序流程无法按预期工作,则最好发出一个强信号,而不是将默认值打印为错误的结果.

Since the compiler doesn’t understand that now only one of the four valid inputs may occur, we have to put a throwing statement to the default case of the switch, as otherwise the compiler will say that result may not have been initialized. We could initialize result to a default value instead, but it’s better to have a strong signal if the program flow doesn’t work as expected, instead of printing a default value as wrong result.

Scanner使用可配置的定界符来确定组成令牌的内容,因此该解决方案使用useDelimiter("\\R")将换行符用作定界符,将每一行视为一个令牌,就像您的原始代码一样.因此, Pattern有关语法的完整说明.

The Scanner uses configurable delimiters to decide what constitutes a token, so this solution uses useDelimiter("\\R") to use line breaks as delimiter, to consider each line a token, like your original code. So the Pattern class for a full description of the syntax.

这篇关于是否可以将try与资源以及输入流一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆