Java调用System.in.read()时控制台Not a valid entry!重复输出是什么原因?
问题原因
System.in.read()每次仅读取输入流中的单个字节,而你在控制台输入内容后按下的回车键,在Windows系统下会生成\r(回车符)和\n(换行符)两个连续的控制字符。- 以输入
1后按回车为例,输入流中实际会依次存在'1'、'\r'、'\n'三个字符:第一次read()读取到'1',匹配对应case正常执行;第二次循环read()不会阻塞,直接读取到'\r',不匹配任何case进入default输出错误;第三次循环read()依然不阻塞,读取到'\n',再次进入default输出错误,就是你看到的重复提示两次的现象。
修复方案
方案1:适配当前System.in.read()逻辑,主动消耗残留控制字符
修改循环内的读取逻辑,每次读取完选择字符后,循环丢弃输入流中剩余的回车、换行符即可:
System.out.print("PASSCODE: "); passcode = (char) System.in.read(); // 先消耗密码输入后的回车换行 while(System.in.available() > 0) { char skip = (char) System.in.read(); if(skip == '\n') break; } if(passcode == '}'){ System.out.println("Welcome! Enter 'Q' to exit at any time!"); System.out.println("1) Website A \n2) Website B \n3) Website C \n4) Website D"); for(;(char) choice != 'Q';){ System.out.print("SELECT: "); choice = (char) System.in.read(); // 消耗每次选择输入后的回车换行 while(System.in.available() > 0) { char skip = (char) System.in.read(); if(skip == '\n') break; } switch(choice){ case '1': websiteA.Display(); break; case '2': websiteB.Display(); break; case '3': websiteC.Display(); break; case '4': websiteD.Display(); break; default: System.out.println("\nNot a valid entry!"); } } } else {System.out.println("ACCESS DENIED");}
方案2:使用Scanner类处理输入,规避底层字符流细节
对于入门开发者更推荐这个方案,Scanner可以直接按行读取输入,自动处理回车换行,大幅降低踩坑概率:
首先在代码顶部导入类:
import java.util.Scanner;
修改后的业务逻辑:
Scanner sc = new Scanner(System.in); System.out.print("PASSCODE: "); // 直接读取整行输入,取第一个字符作为密码 String passLine = sc.nextLine(); char passcode = passLine.length() > 0 ? passLine.charAt(0) : ' '; if(passcode == '}'){ System.out.println("Welcome! Enter 'Q' to exit at any time!"); System.out.println("1) Website A \n2) Website B \n3) Website C \n4) Website D"); String choiceLine; while(!(choiceLine = sc.nextLine()).equals("Q")){ if(choiceLine.length() == 0) { System.out.println("\nNot a valid entry!"); System.out.print("SELECT: "); continue; } char choice = choiceLine.charAt(0); switch(choice){ case '1': websiteA.Display(); break; case '2': websiteB.Display(); break; case '3': websiteC.Display(); break; case '4': websiteD.Display(); break; default: System.out.println("\nNot a valid entry!"); } System.out.print("SELECT: "); } } else { System.out.println("ACCESS DENIED"); } sc.close();
内容的提问来源于stack exchange,提问作者Kaleb Dodge
相关产品推荐
相关产品推荐

