ZetCode

Java LineNumberReader 类

最后修改时间:2025 年 4 月 16 日

java.io.LineNumberReader 类是一个缓冲字符输入流,它可以跟踪行号。它扩展了 BufferedReader 并添加了行计数功能。行号默认从 0 开始。

当处理行号很重要的文本文件时,LineNumberReader 非常有用。它提供了获取和设置当前行号的方法。该类会自动处理不同的行终止约定。

LineNumberReader 类概述

LineNumberReader 扩展了 BufferedReader 并添加了行号跟踪功能。关键方法包括行号访问、读取操作和标记/重置功能。该类将 '\n'、'\r' 或 "\r\n" 识别为行终止符。

public class LineNumberReader extends BufferedReader {
    public LineNumberReader(Reader in);
    public LineNumberReader(Reader in, int sz);
    public int getLineNumber();
    public void setLineNumber(int lineNumber);
    public String readLine();
    public int read();
    public int read(char[] cbuf, int off, int len);
    public long skip(long n);
    public void mark(int readAheadLimit);
    public void reset();
    public boolean markSupported();
    public void close();
}

上面的代码显示了 LineNumberReader 提供的关键方法。这些方法允许在跟踪行号的同时读取文本。该类继承了 BufferedReader 的缓冲功能。

创建 LineNumberReader

LineNumberReader 是通过将其包装在另一个 Reader 周围创建的。您可以指定缓冲区大小或使用默认值。行号从 0 开始,但可以初始设置为任何值。

Main.java
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Main {

    public static void main(String[] args) {
        try {
            // Create with default buffer size
            LineNumberReader reader1 = 
                new LineNumberReader(new FileReader("data.txt"));
            
            // Create with custom buffer size (8KB)
            LineNumberReader reader2 = 
                new LineNumberReader(new FileReader("data.txt"), 8192);
            
            // Set initial line number
            reader2.setLineNumber(10);
            
            System.out.println("Reader1 line: " + reader1.getLineNumber());
            System.out.println("Reader2 line: " + reader2.getLineNumber());
            
            reader1.close();
            reader2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了创建 LineNumberReader 的不同方法。第一个使用默认缓冲区大小,而第二个指定 8KB。第二个读取器的行号设置为 10。始终在使用完毕后关闭读取器。

读取带有行号的行

LineNumberReader 的主要功能是在跟踪行号的同时读取行。readLine 方法返回每一行并自动递增行计数器。行号从 0 开始,除非另行设置。

Main.java
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Main {

    public static void main(String[] args) {
        try (LineNumberReader reader = 
                new LineNumberReader(new FileReader("data.txt"))) {
            
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.printf("Line %d: %s%n", 
                    reader.getLineNumber(), line);
            }
            
            System.out.println("Total lines: " + reader.getLineNumber());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了如何逐行读取文件并带有行号。readLine 方法在文件末尾返回 null。请注意,getLineNumber 返回要读取的下一行的编号。try-with-resources 确保正确关闭读取器。

读取带有行跟踪的字符

LineNumberReader 也可以读取单个字符,同时保持行号跟踪。每个换行符都会递增行计数器。这在逐字符处理时提供了灵活性。

Main.java
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Main {

    public static void main(String[] args) {
        try (LineNumberReader reader = 
                new LineNumberReader(new FileReader("data.txt"))) {
            
            int charValue;
            while ((charValue = reader.read()) != -1) {
                char c = (char) charValue;
                if (c == '\n' || c == '\r') {
                    System.out.printf("(Line %d end)%n", reader.getLineNumber());
                } else {
                    System.out.print(c);
                }
            }
            
            System.out.println("Final line number: " + reader.getLineNumber());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了逐字符读取并带有行号跟踪。该代码检测行尾并打印当前行号。read 方法在流末尾返回 -1。所有行结束约定都会自动处理。

使用行号标记和重置

LineNumberReader 支持标记和重置操作,同时保持行号状态。mark 方法会记住当前位置和行号。Reset 返回到标记的位置并恢复行号。

Main.java
import java.io.StringReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Main {

    public static void main(String[] args) {
        String text = "First line\nSecond line\nThird line";
        
        try (LineNumberReader reader = 
                new LineNumberReader(new StringReader(text))) {
            
            // Read first line
            System.out.println("Line " + reader.getLineNumber() + 
                ": " + reader.readLine());
            
            // Mark current position
            reader.mark(100);
            
            // Read second line
            System.out.println("Line " + reader.getLineNumber() + 
                ": " + reader.readLine());
            
            // Reset to marked position
            reader.reset();
            
            // Read again from mark
            System.out.println("After reset, line " + reader.getLineNumber() + 
                ": " + reader.readLine());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例显示了带有行号的标记/重置功能。标记在读取第一行后设置。在读取第二行后,reset 返回到标记的位置。行号在重置期间得到正确恢复。

跳过行和字符

LineNumberReader 提供了 skip 方法来跳过字符,同时保持行计数。跳过换行符会递增行计数器。实际跳过的字符数可能少于请求的字符数。

Main.java
import java.io.StringReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Main {

    public static void main(String[] args) {
        String text = "Line 1\nLine 2\nLine 3\nLine 4";
        
        try (LineNumberReader reader = 
                new LineNumberReader(new StringReader(text))) {
            
            System.out.println("Initial line: " + reader.getLineNumber());
            
            // Skip first 8 characters (past first line)
            long skipped = reader.skip(8);
            System.out.println("Skipped " + skipped + " characters");
            System.out.println("Current line: " + reader.getLineNumber());
            
            // Read next line
            System.out.println("Next line: " + reader.readLine());
            
            // Skip beyond end of input
            skipped = reader.skip(20);
            System.out.println("Skipped " + skipped + " characters at end");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了在跟踪行号的同时跳过字符。跳过第一行的换行符会递增行计数器。第二次跳过尝试跳过超过输入结束的位置。实际跳过的计数可能少于请求的计数。

设置自定义行号

LineNumberReader 允许将当前行号设置为任何值。这在处理部分文件或组合多个输入时很有用。可以在读取期间的任何时间设置行号。

Main.java
import java.io.StringReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Main {

    public static void main(String[] args) {
        String text = "Alpha\nBeta\nGamma\nDelta";
        
        try (LineNumberReader reader = 
                new LineNumberReader(new StringReader(text))) {
            
            // Set custom starting line number
            reader.setLineNumber(100);
            
            // Read first line
            System.out.println("Line " + reader.getLineNumber() + 
                ": " + reader.readLine());
            
            // Increment line number manually
            reader.setLineNumber(reader.getLineNumber() + 5);
            
            // Read next line
            System.out.println("Line " + reader.getLineNumber() + 
                ": " + reader.readLine());
            
            // Reset to specific line number
            reader.setLineNumber(200);
            System.out.println("Line " + reader.getLineNumber() + 
                ": " + reader.readLine());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了如何手动控制行编号。初始行号设置为 100。该代码演示了手动递增和设置特定行号。当处理部分文件或组合多个输入时,这种灵活性很有帮助。

来源

Java LineNumberReader 类文档

在本文中,我们介绍了 Java LineNumberReader 类的基本方法和功能。理解这些概念对于在 Java 应用程序中使用带行号的文本处理至关重要。

作者

我的名字是 Jan Bodnar,我是一位经验丰富的专业程序员。我于 2007 年开始撰写编程文章,至今已撰写超过 1400 篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程