1. 概述
在本文中,我们将深入探讨 Java 中 BufferedReader、Console 和 Scanner 类之间的区别。
如果你希望更深入地了解每一个类,建议参考我们之前的相关文章:Java Scanner、Java 控制台输入输出 和 BufferedReader。
2. 用户输入处理能力
根据传入构造函数的底层流不同,BufferedReader 和 Scanner 都可以处理多种类型的输入源,例如字符串、文件、系统控制台(通常连接键盘)以及 Socket 输入流等。
而 Console 类则专门用于访问与当前 JVM 关联的字符型系统控制台(如果存在的话)。
来看一下 BufferedReader 的几种构造方式,支持多种输入来源:
BufferedReader br = new BufferedReader(
new StringReader("Bufferedreader vs Console vs Scanner in Java"));
BufferedReader br = new BufferedReader(
new FileReader("file.txt"));
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in))
Socket socket = new Socket(hostName, portNumber);
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
Scanner 同样支持类似的输入源:
Scanner sc = new Scanner("Bufferedreader vs Console vs Scanner in Java")
Scanner sc = new Scanner(new File("file.txt"));
Scanner sc = new Scanner(System.in);
Socket socket = new Socket(hostName, portNumber);
Scanner sc = new Scanner(socket.getInputStream());
而 Console 只能通过以下方式获取实例:
Console console = System.console();
⚠️ 注意:当你使用 Console 类时,若程序运行在 Eclipse 或 IntelliJ IDEA 等 IDE 中,则 JVM 关联的系统控制台不可用。
3. 输出功能对比
与 BufferedReader 和 Scanner 不同,Console 类提供了便捷的方法来向控制台输出提示信息,如:
readPassword(String fmt, Object… args)
readLine(String fmt, Object… args)
printf(String format, Object… args)
这使得我们可以省去手动调用 System.out.println
来打印提示语:
String firstName = console.readLine("Enter your first name please: ");
console.printf("Welcome " + firstName );
✅ 如果你在编写一个需要与系统控制台交互的程序,那么 Console 类会让你的代码更加简洁。
4. 解析输入的能力
Scanner 提供了强大的解析能力,可以按正则表达式将输入拆分为 token,默认以空白字符为分隔符:
String input = "Bufferedreader vs Console vs Scanner";
Scanner sc = new Scanner(input).useDelimiter("\\s*vs\\s*");
System.out.println(sc.next());
System.out.println(sc.next());
System.out.println(sc.next());
sc.close();
相比之下,BufferedReader 和 Console 只是原样读取输入流,不做额外处理。
5. 安全数据读取
Console 提供了两个方法用于安全输入(关闭回显):
readPassword()
readPassword(String fmt, Object… args)
比如读取密码:
String password = String.valueOf(console.readPassword("Password :"));
❌ 而 BufferedReader 和 Scanner 并不具备这个能力。
6. 线程安全性
- BufferedReader 的 read 方法是 synchronized
- Console 的 read 和 write 方法也是 synchronized
- ❌ Scanner 的相关方法 不是线程安全的
✅ 因此,在多线程环境下读取用户输入时,优先考虑 BufferedReader 或 Console。
7. 缓冲区大小
- BufferedReader 的缓冲区默认为 8KB
- Scanner 的缓冲区只有 1KB
- BufferedReader 支持自定义缓冲区大小,适用于读取大段文本
- Console 在读取时不使用缓冲区,但在写入时使用了带缓冲的输出流
8. 其他细节差异
虽然这些点不构成选型的主要依据,但仍然值得关注。
8.1. 流关闭操作
- 创建 BufferedReader 或 Scanner 后,必须手动关闭以避免内存泄漏
- Console 则无需手动关闭
8.2. 异常处理机制
- Scanner 和 Console 使用的是非检查型异常(unchecked exception)
- BufferedReader 的方法抛出的是检查型异常(checked exception),强制你写 try-catch
9. 总结:如何选择?
以下是一些实用建议,帮助你根据不同场景做出合理选择:
✅ 使用 BufferedReader 的情况:
- 从文件中读取长文本(性能更好)
✅ 使用 Console 的情况:
- 从系统控制台读取敏感信息(如密码),并希望隐藏输入内容
✅ 使用 Scanner 的情况:
- 需要对输入进行正则匹配或类型解析
- 与控制台交互且不需要线程安全时(因其 API 更灵活)
✅ 多线程场景下:
- 优先使用 BufferedReader(除非必须使用 Console 特性)
📌 总之,没有“最好的”工具,只有“最合适的”。理解它们各自的优缺点,才能写出更高效、健壮的代码。