LineNumberInputStream 已被弃用并移除,因其仅支持 LF 换行、无法处理多字节字符且行号逻辑不可靠;推荐使用 BufferedReader 或自定义 LineNumberReader,基于字符流确保编码安全与行号准确。

注意:LineNumberInputStream 已在 Java 1.1 中被弃用,自 Java 9 起已彻底移除,不推荐、也不支持在现代 Java(JDK 8+)中使用。
它曾是 FilterInputStream 的子类,用于为字节流添加行号计数功能,但存在严重缺陷:
- 仅按
\n(LF)识别换行,不兼容 Windows 的\r\n或旧 Mac 的\r; - 基于字节流,无法正确处理多字节字符(如 UTF-8 中的中文),可能导致行号错乱或乱码;
- 行号逻辑与实际文本行语义脱节,不可靠。
替代方案:用字符流 + BufferedReader 记录行号
Java 推荐使用基于字符的 API 处理文本。BufferedReader 提供了稳定、编码安全的行读取能力,并可轻松跟踪行号:
✅ 正确做法(JDK 7+ 推荐):
立即学习“Java免费学习笔记(深入)”;
try (BufferedReader reader = Files.newBufferedReader(Paths.get("data.txt"), StandardCharsets.UTF_8)) {
String line;
int lineNumber = 0;
while ((line = reader.readLine()) != null) {
lineNumber++;
System.out.println("第 " + lineNumber + " 行: " + line);
}
}? 小技巧:封装成带行号的迭代器或自定义包装类,复用更方便:
public class LineNumberReader extends BufferedReader {
private int lineNumber = 0;
public LineNumberReader(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
String line = super.readLine();
if (line != null) lineNumber++;
return line;
}
public int getLineNumber() {
return lineNumber;
}
}使用:
try (LineNumberReader lnr = new LineNumberReader(
Files.newBufferedReader(Paths.get("log.txt"), StandardCharsets.UTF_8))) {
String line;
while ((line = lnr.readLine()) != null) {
System.out.printf("L%d: %s%n", lnr.getLineNumber(), line);
}
}如果必须处理原始字节流(极少数场景)
例如解析二进制协议中夹带的 ASCII 行文本,且明确知道换行符格式(如纯 \n),可手动实现轻量行号计数:
⚠️ 注意:这仍是字节层面操作,不解析编码,仅适用于 ASCII 或已知单字节编码:
try (InputStream is = Files.newInputStream(Paths.get("ascii.log"))) {
int b;
int lineNumber = 1;
while ((b = is.read()) != -1) {
if (b == '\n') {
System.out.println("行号 " + lineNumber + " 结束");
lineNumber++;
}
// 可选择缓冲或处理单字节...
}
}? 关键点:
- 手动维护 `lineNumber`,遇到 `\n` 就加 1;
- 不依赖任何废弃类,完全可控;
- 若需按行获取内容,建议仍先转为字符串(指定 Charset),再用 `String.split("\n")` 或 `BufferedReader`。
为什么不能“修复”或“重新启用” LineNumberInputStream
它不是 bug,而是设计过时:
- 字节流无法感知字符边界 → 对 UTF-8/GBK 等编码完全失效;
- 换行判断逻辑硬编码 → 无法适配不同平台;
- API 不符合现代 Java 的 I/O 分层理念(字节流 vs 字符流职责分离)。
强行通过反射或旧 JDK 运行,只会掩盖问题,带来难以调试的文本处理错误。
不复杂但容易忽略:处理文本,请用字符流;需要行号,请用 BufferedReader 或自行封装。


















