scanner.nextline() 读不到输入是因为 nextint() 等方法不消费换行符,导致 nextline() 立即读取残留的 而返回空字符串;正确做法是在 nextint() 后加一次 nextline() 清缓存或统一用 nextline() 配合 parsexxx() 转换。

Scanner.nextLine() 为什么总读不到输入?
因为 nextLine() 会消费换行符,而它前面如果用了 nextInt()、nextDouble() 等非行读取方法,这些方法不会吃掉用户敲回车留下的
,导致 nextLine() 立刻读到空行。
常见错误现象:nextInt() 后接 nextLine(),结果后者返回空字符串;控制台光标一闪就跳过输入。
- 正确做法:在
nextInt()后手动加一次nextLine()清掉残留换行符 - 或者统一用
nextLine()读所有输入,再用Integer.parseInt()等转换 - 注意:
hasNextLine()不会阻塞,但nextLine()会等待用户输入,别在循环条件里混用
用 Scanner 解析 CSV 或空格分隔的字符串时,delimeter 设错会丢数据
默认分隔符是空白字符(空格、制表符、换行),但遇到含空格的字段(如 "John Doe")就会切碎。想按逗号或固定符号切,必须显式调用 useDelimiter()。
使用场景:读配置行、解析日志片段、处理剪贴板粘贴的表格文本。
立即学习“Java免费学习笔记(深入)”;
- 设为逗号:用
scanner.useDelimiter(","),但注意它不自动跳过前后空格,常需配合trim() - 设为正则:比如
scanner.useDelimiter("\s*,\s*")可同时处理逗号和周围空格 - 误设成
"\n"会导致整行当一个 token,失去字段级解析能力 - 每次改
useDelimiter()都影响后续所有读取,别在同一个 scanner 实例里反复切换
Scanner 关闭后继续调用 nextXXX() 报 NoSuchElementException
一旦调用 close(),底层关联的 System.in 流也被关闭——这不是 Scanner 自己“失活”,而是系统输入流真没了,再读就抛异常。
性能影响:不关 Scanner 不会内存泄漏,但长期运行的服务里留着未关闭的 scanner 可能阻碍资源回收(尤其包装了文件流时)。
- 只读控制台输入时,通常不用主动
close();关了反而后续无法再读 - 若 scanner 包装的是文件(
new Scanner(new File("a.txt"))),必须关,否则文件句柄泄露 - 别在 try-with-resources 里包
System.in的 scanner,因为关了就再也打不开 - 检查是否已关闭:没有公开 API,只能靠自己记状态或捕获
IllegalStateException
中文输入乱码或 next() 卡住?查编码和输入源类型
Scanner 本身不处理编码,它依赖底层 InputStream 或 Reader 的解码逻辑。直接包装 System.in 时,用的是平台默认编码,Windows 常是 GBK,IDE 运行时可能是 UTF-8,不一致就乱码。
使用场景:在 IntelliJ/Eclipse 里跑 Scanner,输入中文却显示问号或异常字符。
- 安全做法:不要用
new Scanner(System.in),改用new Scanner(new InputStreamReader(System.in, "UTF-8")) - IDE 控制台编码设置必须和代码里指定的一致,IntelliJ 在 Settings → Editor → File Encodings 里调
- 如果输入来自文件,确保文件保存编码与 scanner 指定编码相同,否则
hasNext()可能永远返回 false - 注意:Android 不支持
System.in,这类代码不能直接搬过去
Scanner 表面简单,但每个方法背后都绑着流状态、编码、分隔逻辑三层依赖;最容易被忽略的是「谁关了流」和「换行符去哪了」这两件事。










