Java使用System.in.read()的do-while循环重复输出的原因是什么?
核心问题原因
提示语句重复输出,本质是程序把用户按下回车键时伴随产生的控制字符当成了需要判断的有效输入,触发了额外的循环执行,你最初的猜测方向完全准确。
具体的运行逻辑拆解:
System.in.read()是基于字节流的底层读取方法,每次调用只会从控制台的输入缓冲区中读取1个字节,读到内容就立刻返回,不会自动过滤回车、换行这类控制字符- 在Windows控制台场景下,输入一个可见字符(比如按
a)再敲回车,操作系统会往输入缓冲区写入3个字节:输入字符对应的ASCII码、回车符\r(ASCII码13)、换行符\n(ASCII码10);在Linux/macOS场景下会写入2个字节:输入的字符、换行符\n - do-while循环每执行一轮,就会先打印一次提示语句。只要缓冲区里还有没被读走的残留字节,循环就会继续运行、继续打印提示,直到把缓冲区里所有字节读完,才会停下来等待下一次输入——你看到的提示重复多次,并不是同一段提示被打印了好几遍,是循环因为读取了残留的控制字符,多跑了几轮而已。
常见解决方案
方案1:每次读取有效字符后清空输入缓冲区
在每次读取到用户输入的字符后,立刻把缓冲区里残留的回车、换行等控制符全部读取丢弃,避免残留字节触发多余循环:
public class DoWhile { public static void main(String[] args) throws java.io.IOException { char ch; do { System.out.print("Press a key followed by ENTER : "); ch = (char)System.in.read(); // 清空当前缓冲区所有剩余的可读内容 while (System.in.available() > 0) { System.in.read(); } } while (ch != 'q'); } }
补充说明:System.in.available()会返回当前输入缓冲区里可以无阻塞读取的字节数,只要数值大于0,就说明还有刚才敲回车带进来的残留内容,全部读完丢弃即可。
方案2:换用高层输入类自动处理分隔符
放弃直接使用System.in.read()这种底层读取API,改用自带输入分隔符处理逻辑的输入类(比如Scanner)。这类类会自动跳过回车、空格这类控制分隔符,不会把它们当成有效输入读取:
import java.util.Scanner; public class DoWhile { public static void main(String[] args) { Scanner inputScanner = new Scanner(System.in); char ch; do { System.out.print("Press a key followed by ENTER : "); // 自动跳过前后的分隔符,读取第一个有效输入字符 ch = inputScanner.next().charAt(0); } while (ch != 'q'); inputScanner.close(); } }
内容的提问来源于stack exchange,提问作者Emeraldo
相关产品推荐
相关产品推荐

