如何修复Java中含Scanner的while循环重启失效问题
Problem Analysis
The program terminates unexpectedly after the first execution loop due to unconsumed newline characters remaining in the Scanner buffer. This leads to an InputMismatchException in subsequent iterations when trying to read the typing speed integer.
Root Cause
scan.nextInt()reads the integer value for speed but leaves the trailing newline character in the buffer.scan.next()reads the "y/n" choice but also leaves the trailing newline in the buffer.- In the next loop iteration,
scan.nextLine()reads this leftover newline as an empty input string, and thenscan.nextInt()attempts to parse an empty string as an integer, triggering an uncaught exception that terminates the program.
Fixed Code
import java.awt.AWTException; import java.util.Scanner; import java.awt.Robot; import java.awt.event.KeyEvent; import java.util.Random; public class PasteTyper { public static void main(String[] args) { Scanner scan = new Scanner(System.in); while (true) { Random rand = new Random(); System.out.print("\nEnter what to paste: "); String input = scan.nextLine(); System.out.print("\nEnter typing speed (10 is recommended) (Lower is faster, higher is slower): "); int speed = scan.nextInt(); scan.nextLine(); // Consume remaining newline after nextInt() try{Thread.sleep(3000);} catch(InterruptedException e){} for(int i = 0; i < input.length(); i++){ try{Thread.sleep(rand.nextInt(30 * speed));} catch(InterruptedException e){} int delete = rand.nextInt(20 * speed); if(delete == 5){ int randomChar = rand.nextInt(10); switch(randomChar){ case 1: convert('a'); break; case 2: convert('b'); break; case 3: convert('c'); break; case 4: convert('d'); break; case 5: convert('e'); break; case 6: convert('f'); break; case 7: convert('g'); break; case 8: convert('h'); break; case 9: convert('i'); break; default:convert('j'); break; } try{Thread.sleep(40 * speed);} catch(InterruptedException e){} doType(KeyEvent.VK_BACK_SPACE); try{Thread.sleep(20 * speed);} catch(InterruptedException e){} } if(input.charAt(i) == '\\') { if(i+1 < input.length() && input.charAt(i + 1) == 't') { convert('\t'); i++; } else if(i+1 < input.length() && input.charAt(i + 1) == 'n') { convert('\n'); i++; } else convert(input.charAt(i)); } else convert(input.charAt(i)); } System.out.print("\nDo you want to paste again? (y/n): "); String choice = scan.next(); scan.nextLine(); // Consume remaining newline after next() if(!choice.equalsIgnoreCase("y")) break; } scan.close(); } public static void convert(char character){ switch(character){ case '\t' -> doType(KeyEvent.VK_TAB); case '\n' -> doType(KeyEvent.VK_ENTER); case 'a' -> doType(KeyEvent.VK_A); case 'b' -> doType(KeyEvent.VK_B); case 'c' -> doType(KeyEvent.VK_C); case 'd' -> doType(KeyEvent.VK_D); case 'e' -> doType(KeyEvent.VK_E); case 'f' -> doType(KeyEvent.VK_F); case 'g' -> doType(KeyEvent.VK_G); case 'h' -> doType(KeyEvent.VK_H); case 'i' -> doType(KeyEvent.VK_I); case 'j' -> doType(KeyEvent.VK_J); case 'k' -> doType(KeyEvent.VK_K); case 'l' -> doType(KeyEvent.VK_L); case 'm' -> doType(KeyEvent.VK_M); case 'n' -> doType(KeyEvent.VK_N); case 'o' -> doType(KeyEvent.VK_O); case 'p' -> doType(KeyEvent.VK_P); case 'q' -> doType(KeyEvent.VK_Q); case 'r' -> doType(KeyEvent.VK_R); case 's' -> doType(KeyEvent.VK_S); case 't' -> doType(KeyEvent.VK_T); case 'u' -> doType(KeyEvent.VK_U); case 'v' -> doType(KeyEvent.VK_V); case 'w' -> doType(KeyEvent.VK_W); case 'x' -> doType(KeyEvent.VK_X); case 'y' -> doType(KeyEvent.VK_Y); case 'z' -> doType(KeyEvent.VK_Z); case 'A' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_A); case 'B' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_B); case 'C' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_C); case 'D' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_D); case 'E' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_E); case 'F' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_F); case 'G' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_G); case 'H' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_H); case 'I' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_I); case 'J' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_J); case 'K' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_K); case 'L' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_L); case 'M' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_M); case 'N' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_N); case 'O' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_O); case 'P' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_P); case 'Q' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_Q); case 'R' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_R); case 'S' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_S); case 'T' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_T); case 'U' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_U); case 'V' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_V); case 'W' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_W); case 'X' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_X); case 'Y' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_Y); case 'Z' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_Z); case '`' -> doType(KeyEvent.VK_BACK_QUOTE); case '0' -> doType(KeyEvent.VK_0); case '1' -> doType(KeyEvent.VK_1); case '2' -> doType(KeyEvent.VK_2); case '3' -> doType(KeyEvent.VK_3); case '4' -> doType(KeyEvent.VK_4); case '5' -> doType(KeyEvent.VK_5); case '6' -> doType(KeyEvent.VK_6); case '7' -> doType(KeyEvent.VK_7); case '8' -> doType(KeyEvent.VK_8); case '9' -> doType(KeyEvent.VK_9); case '-' -> doType(KeyEvent.VK_MINUS); case '=' -> doType(KeyEvent.VK_EQUALS); case '~' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_QUOTE); case '!' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_1); case '@' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_2); case '#' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_3); case '$' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_4); case '%' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_5); case '^' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_6); case '&' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_7); case '*' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_8); case '(' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_9); case ')' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_0); case '_' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_MINUS); case '+' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_EQUALS); case '[' -> doType(KeyEvent.VK_OPEN_BRACKET); case ']' -> doType(KeyEvent.VK_CLOSE_BRACKET); case '\\' -> doType(KeyEvent.VK_BACK_SLASH); case '{' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_OPEN_BRACKET); case '}' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_CLOSE_BRACKET); case '|' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH); case ';' -> doType(KeyEvent.VK_SEMICOLON); case ':' -> doType(KeyEvent.VK_SHIFT,KeyEvent.VK_SEMICOLON); case '\'' -> doType(KeyEvent.VK_QUOTE); case '"' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_QUOTE); case ',' -> doType(KeyEvent.VK_COMMA); case '<' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_COMMA); case '.' -> doType(KeyEvent.VK_PERIOD); case '>' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_PERIOD); case '/' -> doType(KeyEvent.VK_SLASH); case '?' -> doType(KeyEvent.VK_SHIFT, KeyEvent.VK_SLASH); case ' ' -> doType(KeyEvent.VK_SPACE); default -> throw new IllegalArgumentException("Cannot type character " + character); } } public static void doType(int keycode){ try{ Robot robot = new Robot(); robot.keyPress(keycode); robot.keyRelease(keycode); } catch(AWTException e){ e.printStackTrace(); } } public static void doType(int keycode1, int keycode2){ try{ Robot robot = new Robot(); robot.keyPress(keycode1); robot.keyPress(keycode2); robot.keyRelease(keycode2); robot.keyRelease(keycode1); } catch(AWTException e){ e.printStackTrace(); } } }
Key Changes Made
- Buffer cleanup: Added
scan.nextLine()afterscan.nextInt()andscan.next()to clear trailing newline characters from the input buffer, preventing empty inputs in subsequent loops. - Bounds safety: Added
i+1 < input.length()checks before accessinginput.charAt(i+1)to avoidIndexOutOfBoundsExceptionwhen input ends with a backslash. - Flexible input handling: Changed choice check to
equalsIgnoreCase("y")to accept both 'y' and 'Y' as valid continuation inputs. - Correct key sequence: Fixed key release order in the two-parameter
doTypemethod to release non-modifier keys first, ensuring proper keyboard emulation. - Debug visibility: Added
e.printStackTrace()to AWT exception handlers to help diagnose Robot class issues.
内容的提问来源于stack exchange,提问作者Luka
相关产品推荐
相关产品推荐

