Java自定义TimedScanner使用后普通Scanner需两次回车输入问题求助
问题原因与解决方案
核心问题根源
你的问题确实和同时使用两个绑定System.in的Scanner实例直接相关,同时还有后台线程抢占输入的问题:
System.in是JVM全局的输入流,多个Scanner绑定同一个输入流时,每个Scanner会有独立的缓冲区,提前读取的内容不会共享,会导致后续Scanner读不到输入。- 你创建的
TimedScanner实例启动了常驻后台线程,一直在循环调用内部Scanner的hasNextLine()方法阻塞等待输入,所有输入会优先被这个后台线程捕获。当你调用完带超时的nextLine()方法后,reading变量被置为false,此时后台线程拿到输入后会直接清空缓冲区,相当于把后续要给普通Scanner的输入直接吞掉,所以第一次输入的内容永远读不到,才会出现需要按两次回车才能读取的现象。
可行修复方案
不要额外创建新的普通Scanner实例,直接复用TimedScanner的内部输入逻辑,给TimedScanner新增一个无超时的普通nextLine()方法即可:
// 新增到TimedScanner类中 public String nextLine() { synchronized (buffer) { buffer.delete(0, buffer.length()); } reading = true; String result = null; // 无超时等待输入 while (result == null) { try { Thread.sleep(30); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } synchronized (buffer) { if (buffer.length() > 0) { Scanner temp = new Scanner(buffer.toString()); result = temp.nextLine(); buffer.delete(0, buffer.length()); break; } } } reading = false; return result; }
然后修改main函数else分支的逻辑,删掉创建scanner1的代码,直接调用原有scanner对象的无超时nextLine()方法:
else { // 删掉原有Scanner scanner1 = new Scanner(System.in);代码 int number = Integer.parseInt(input); File myFile = new File("searchagent_list.txt"); if (!myFile.exists()) { myFile.createNewFile(); } // 补充缺失的导包:import java.io.BufferedWriter; for (int i = 0; i < number; i++) { System.out.println("Enter the name of searchagent #"+(i+1)); String name = scanner.nextLine(); System.out.println("Enter the adress of searchagent #"+(i+1)); String adress = scanner.nextLine(); FileWriter fWrite = new FileWriter(myFile, true); BufferedWriter bWrite = new BufferedWriter(fWrite); bWrite.write(name+"##"+adress+"##\n"); bWrite.close(); } System.out.println("Done"); }
修改完成后所有输入都走同一个Scanner实例,不会出现流抢占和输入丢失的问题,无需多次按回车即可正常读取。
内容的提问来源于stack exchange,提问作者Cremejoghurt
相关产品推荐
相关产品推荐

