使用Scanner类
✅ 适用场景
适合交互式控制台输入,支持自动解析基本数据类型(整型/浮点型),代码简洁易读。
🔧 实现步骤
- 导入包与初始化对象
需先引入java.util.Scanner
,并通过new Scanner(System.in)
创建实例。import java.util.Scanner; Scanner scanner = new Scanner(System.in);
- 读取整行字符串
调用nextLine()
获取用户输入的完整行内容(包括空格):System.out.println("请输入一串数字,用空格分隔:"); String inputLine = scanner.nextLine(); // 读取直到换行符
- 拆分并转换数据类型
利用split(" ")
按空格分割字符串为数组,再通过循环转换为目标类型:String[] parts = inputLine.split("\s+"); // 正则匹配多个连续空格 int[] nums = new int[parts.length]; for (int i = 0; i < parts.length; i++) { nums[i] = Integer.parseInt(parts[i]); // 转为整数 }
- 异常处理机制
若用户误输非数字字符,会抛出NumberFormatException
,可通过try-catch
捕获:try { nums[i] = Integer.parseInt(parts[i]); } catch (NumberFormatException e) { System.out.println("第" + (i+1) + "项不是有效整数!"); }
- 关闭资源
使用完毕后调用scanner.close()
释放底层IO资源。
⚙️ 优缺点对比
优点 | 缺点 |
---|---|
API简单直观 | 大文件场景性能较低 |
内置类型解析功能 | 无法直接控制缓冲区大小 |
支持混合数据格式输入 | 多线程环境下不安全 |
使用BufferedReader类
✅ 适用场景
高效处理大量文本流输入,尤其适合逐行读取长文本或日志文件。
🔧 实现步骤
- 嵌套包装器构建通道
需组合InputStreamReader
和BufferedReader
两层封装:import java.io.; BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- 同步阻塞式读取
调用readLine()
方法会一直等待用户回车确认:System.out.println("请输入数据序列:"); String line = null; try { line = reader.readLine(); // 阻塞直至收到换行符 } catch (IOException e) { e.printStackTrace(); }
- 精细化字符串处理
相比Scanner,可更灵活地定义分隔模式:// 例:按逗号分隔CSV格式数据 String[] items = line.split(",");
- 手动类型转换
所有值均以字符串形式返回,需显式调用包装类的静态方法转换:Double dblVal = Double.parseDouble(strItem);
- 显式资源管理
必须在finally块中关闭读取器防止内存泄漏:finally { try { reader.close(); } catch (Exception ignored) {} }
⚙️ 优缺点对比
优点 | 缺点 |
---|---|
I/O效率高(带缓冲区) | API稍复杂 |
支持自定义缓冲区大小 | 无内置类型校验 |
适合文本行级操作 | 错误处理需自行实现 |
使用Console类(JDK特有)
⚠️ 注意事项
仅当JVM检测到标准设备关联了终端时才可用,IDE环境中可能返回null。
🛠️ 典型用法示例
Console cons = System.console(); if (cons != null) { char[] passwordArr = cons.readPassword("请输入密码:"); // 隐藏回显模式 String secret = new String(passwordArr); } else { System.out.println("当前环境不支持控制台交互"); }
此方案主要用于安全敏感场景下的密文输入,普通数据录入较少采用。
综合对比表
特性 | Scanner | BufferedReader | Console |
---|---|---|---|
主要用途 | 通用交互式输入 | 高效文本流处理 | 安全认证场景 |
API复杂度 | 低 | 中等 | 高 |
性能表现 | 一般 | 优秀 | N/A |
类型推断能力 | 自动 | 手动 | 无 |
异常处理友好度 | 较好 | 依赖开发者实现 | 依赖环境支持 |
特殊功能支持 | 自定义缓冲区配置 | 密码掩码显示 |
实战案例演示
假设需要实现一个学生成绩管理系统的数据导入功能,推荐采用如下分层设计:
- 视图层 使用Scanner提供提示信息:“请输入数学成绩→英语成绩→物理成绩”;
- 业务层 创建对应长度的double数组存储各科分数;
- 持久化层 将验证后的数据集写入文件或数据库。
关键代码片段:
Scanner consoleUI = new Scanner(System.in); double[] scores = new double[3]; for (int i = 0; i < scores.length; i++) { System.out.printf("科目%d的成绩:", i+1); while (!consoleUI.hasNextDouble()) { // 确保输入合法性 consoleUI.next(); // 丢弃无效token System.out.println("必须输入数字!请重新输入:"); } scores[i] = consoleUI.nextDouble(); }
FAQs
Q1: 如果用户输入的数据包含非法字符怎么办?
👉 解决方案:对于Scanner方案,可以使用hasNextXxx()
预检查方法(如hasNextInt()
);BufferedReader则需要结合正则表达式进行前置校验。
if (!inputStr.matches("^\d+(\.\d)?$")) { throw new IllegalArgumentException("无效的数字格式"); }
Q2: 如何提高大数据量下的输入效率?
👉 优化建议:优先选用BufferedReader并设置合适缓冲区大小(默认8KB),
BufferedReader br = new BufferedReader(new InputStreamReader(System.in), 8192); // 显式指定8KB缓冲区
同时避免在循环内频繁创建临时对象,改用StringBuilder拼接
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/76137.html