LineNumberReader是字符流,不能直接包装字节流,必须通过InputStreamReader转换编码后使用,行号由readLine()触发递增,从1开始计数。

在 Java 中,LineNumberReader 是字符流(Reader 的子类),**不能直接用于字节流**(如 InputStream)。它必须包装一个字符输入流(如 FileReader、InputStreamReader)才能工作。它的核心作用是:在读取文本行时自动跟踪当前行号,通过 getLineNumber() 获取。
✅ 正确使用 LineNumberReader 的前提
LineNumberReader 是字符流工具,只处理 Unicode 字符,不处理原始字节。因此:
- 不能用
new LineNumberReader(new FileInputStream(...))—— 编译不通过(类型不匹配) - 必须先将字节流转换为字符流:用
InputStreamReader指定编码,再套一层LineNumberReader - 若读取的是本地文件且编码明确(如 UTF-8),推荐直接用
FileReader(但注意它默认使用平台编码,不够健壮)
✅ 基础用法:逐行读取并获取行号
以下是一个安全、推荐的写法(显式指定 UTF-8 编码):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
try (InputStream is = new FileInputStream("data.txt");
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
LineNumberReader lnr = new LineNumberReader(isr)) {
String line;
while ((line = lnr.readLine()) != null) {
int lineNumber = lnr.getLineNumber(); // 行号从 1 开始
System.out.printf("第%d行: %s%n", lineNumber, line);
}
} catch (IOException e) {
e.printStackTrace();
}
注意:readLine() 返回 null 表示已到文件末尾;getLineNumber() 返回的是**已成功读取的行数**,即当前刚读完的那一行的编号(首行为 1)。
立即学习“Java免费学习笔记(深入)”;
✅ 处理空行与行号偏移的细节
LineNumberReader 的行号递增规则是:每调用一次 readLine()(无论内容是否为空),行号 +1。
- 空行(
"")也会使行号加 1 - 如果跳过某些行(比如用
skip()或其他方式读取了部分字符但没调用readLine()),行号不会自动更新 —— 它只响应readLine() - 可手动调用
setLineNumber(int)重置起始行号(例如从第 100 行开始计数)
❌ 常见误区提醒
-
别混淆字节流和字符流:没有
LineNumberInputStream,Java 标准库不提供基于字节的“行号读取器”——因为“行”的概念依赖于字符编码和换行符(\n、\r\n等),字节流无法安全识别 -
不要忽略编码:用
FileReader而不指定编码,可能在不同系统上读错中文等非 ASCII 内容 -
行号不是“当前指针位置”:它只是内部计数器,和底层字节偏移无关;如需定位字节位置,得自己用
InputStream配合mark()/reset()或缓冲统计

















