下面我将从最推荐、最现代的方式开始,逐步介绍其他方法,并分析它们的优缺点和适用场景。

最推荐的方式:Scanner 类 (用于控制台输入)
Scanner 是 Java 5 引入的一个功能强大的文本扫描器,是从控制台读取用户输入最简单、最常用的方式。
基本用法
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
// 1. 创建一个 Scanner 对象,它从标准输入流 (System.in) 读取数据
Scanner scanner = new Scanner(System.in);
System.out.print("请输入你的名字: ");
// 2. 使用 nextLine() 方法读取一整行
String name = scanner.nextLine();
System.out.print("请输入你的年龄: ");
// 3. 使用 nextInt() 读取整数
int age = scanner.nextInt();
// 4. 关闭 Scanner,以释放系统资源(非常重要!)
scanner.close();
System.out.println("你好, " + name + "!你今年 " + age + " 岁。");
}
}
关键点说明
Scanner scanner = new Scanner(System.in);:创建一个Scanner实例,将标准输入流(通常是键盘)作为数据源。scanner.nextLine():读取从当前位置到行尾的所有字符,并返回一个字符串,它会消耗掉换行符。scanner.nextInt(),scanner.nextDouble()等:读取特定类型的值。注意:在使用这些方法后,输入流中可能还残留着一个换行符,这可能会影响后续的nextLine()调用,一个常见的解决方案是,在使用nextInt()后,再加一个scanner.nextLine()来“消耗”掉这个换行符。scanner.close():非常重要!Scanner包装了底层的System.in,如果不关闭,可能会导致资源泄漏,在程序结束前,请务必关闭它。
更现代的方式:Console 类 (用于控制台交互)
Console 类是 Java 6 引入的,专门为控制台应用程序设计,提供了比 Scanner 更高级的功能,比如读取密码(不回显)。
基本用法
import java.io.Console;
public class ConsoleExample {
public static void main(String[] args) {
// 1. 获取系统 Console 对象
Console console = System.console();
// 检查是否在交互式终端中运行(在 IDE 中运行可能返回 null)
if (console == null) {
System.out.println("无法获取 Console 对象,请确保在交互式终端中运行。");
return;
}
// 2. 读取一行普通输入
String username = console.readLine("请输入用户名: ");
// 3. 读取密码(输入时不会显示任何字符)
char[] passwordArray = console.readPassword("请输入密码: ");
// 处理密码(char[] 比 String 更安全,因为可以在用完后清空内存)
String password = new String(passwordArray);
// 4. 用完后清空密码数组,增强安全性
java.util.Arrays.fill(passwordArray, ' ');
System.out.println("欢迎, " + username + "!");
}
}
关键点说明
System.console():获取Console实例。- 重要限制:如果在非交互式环境(如大多数 IDE 的内置终端、或者将输出重定向到文件时)运行,
System.console()会返回null,代码中必须进行null检查。 console.readLine():功能与Scanner.nextLine()类似,但更直接。console.readPassword():最大亮点,用于读取密码,输入时终端不会显示任何字符,安全性更高。char[]密码:readPassword返回char[]而不是String,这是一个重要的安全实践,因为String是不可变的,一旦创建就无法从内存中清除,而char[]可以在使用后被清空,减少密码在内存中停留的时间。
读取文件内容:BufferedReader 类
当你的需求是从文件中逐行读取时,BufferedReader 是最高效、最标准的做法。
基本用法
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderExample {
public static void main(String[] args) {
// 使用 try-with-resources 语句,可以自动关闭资源,避免资源泄漏
try (BufferedReader reader = new BufferedReader(new FileReader("my_file.txt"))) {
String line;
// 4. 循环读取每一行,直到文件末尾 (readLine() 返回 null)
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("读取文件时发生错误: " + e.getMessage());
}
}
}
关键点说明
new BufferedReader(new FileReader("path")):FileReader负责打开文件,BufferedReader包装它,提供带缓冲的读取功能,大大减少磁盘 I/O 次数,效率更高。reader.readLine():核心方法,从文件中读取一行。注意:它不包含行尾的换行符,当到达文件末尾时,它会返回null。- try-with-resources:这是 Java 7 引入的语法糖,只要实现了
AutoCloseable接口(BufferedReader和FileReader都实现了),放在try()括号里的资源都会在try块执行完毕后自动关闭,即使发生异常也会关闭。强烈推荐使用!
其他方式(不推荐用于简单场景)
java.util.Scanner 读取文件
Scanner 也可以用来读取文件,但通常不推荐用它来替代 BufferedReader 处理大文件,因为 Scanner 的功能更偏向于解析和分词,而 BufferedReader 在纯粹的逐行读取性能上更优。

import java.io.File;
import java.util.Scanner;
public class ScannerReadFile {
public static void main(String[] args) throws Exception {
File file = new File("my_file.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
}
}
总结与对比
| 方法 | 主要用途 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|---|
Scanner |
控制台输入 | 简单易用,功能强大(可读取各种类型) | 性能相对较低,需要手动关闭 | 从键盘读取用户输入的首选 |
Console |
控制台交互 | 可读取密码(不回显),API 简洁 | 在非交互式环境中可能返回 null |
需要安全密码输入的控制台应用 |
BufferedReader |
文件读取 | 性能最高,使用 try-with-resources 自动关闭 |
API 相对简单,主要功能就是读行 | 从文件逐行读取的首选,性能关键场景 |
InputStreamReader |
读取字节流为字符流 | 基础,灵活(可指定编码) | 需要自己处理缓冲和行尾,代码更繁琐 | 需要手动处理字符编码等底层细节时 |
快速选择指南
-
我想从键盘读取用户输入(比如在命令行程序中):
- 首选
Scanner。 - 如果需要输入密码,使用
Console(并确保环境支持)。
- 首选
-
我想从一个文本文件中逐行读取内容:
- 首选
BufferedReader,并配合try-with-resources语法。
- 首选
-
我想从一个网络连接或其他输入流中读取:
- 如果输入流是字节流(
InputStream),先用InputStreamReader包装成字符流,再用BufferedReader包装以获得高性能的行读取能力。new BufferedReader(new InputStreamReader(socket.getInputStream()))。
- 如果输入流是字节流(

