是否可以将try与资源以及输入流一起使用? [英] Is it possible to use try with resources along with an input stream?
问题描述
使用资源实现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.
由于编译器不了解现在只有四个有效输入之一可能出现,因此我们必须在switch
的default
情况下添加一个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屋!