ZetCode

Java BufferedReader 类

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

java.io.BufferedReader 类从字符输入流中读取文本,并使用缓冲来提高效率。 它提供了读取文本行的方法,并支持 mark/reset 操作。 BufferedReader 通常包装在其他 Reader 周围。

BufferedReader 通过减少 I/O 操作的数量来提高性能。 它将字符分块读取到缓冲区中。 默认缓冲区大小为 8192 个字符,但可以指定自定义大小。 此类对于并发访问是线程安全的。

BufferedReader 类概述

BufferedReader 继承自 Reader 并提供缓冲字符读取。 关键方法包括行读取、字符读取和 mark/reset 功能。 缓冲区在执行读取操作时填充。

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

上面的代码显示了 BufferedReader 提供的关键方法。 这些方法允许使用缓冲有效地读取文本数据。 如果底层 Reader 支持,则该类支持 mark 和 reset 操作。

创建 BufferedReader

BufferedReader 通过将其包装在另一个 Reader 周围来创建。 您可以指定缓冲区大小或使用默认值。 常见的来源包括用于文件的 FileReader 和用于系统输入或网络流的 InputStreamReader。

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

public class Main {

    public static void main(String[] args) {
        try {
            // Create with default buffer size
            BufferedReader reader1 = new BufferedReader(new FileReader("data.txt"));
            
            // Create with custom buffer size (16KB)
            BufferedReader reader2 = new BufferedReader(
                new FileReader("data.txt"), 16384);
            
            System.out.println("Default buffer reader created");
            System.out.println("Custom buffer (16KB) reader created");
            
            reader1.close();
            reader2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了创建 BufferedReader 的不同方法。 第一个使用默认缓冲区大小,而第二个指定 16KB。 完成后始终关闭 readers 以释放资源。 关闭 BufferedReader 时,底层 FileReader 会自动关闭。

使用 BufferedReader 读取行

readLine 方法是 BufferedReader 最有用的功能之一。 它读取一行文本,在流的末尾返回 null。 行尾可以是 \n、\r 或 \r\n。 该方法对于处理文本文件非常有效。

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

public class Main {

    public static void main(String[] args) {
        try (BufferedReader reader = 
                new BufferedReader(new FileReader("data.txt"))) {
            
            String line;
            int lineNumber = 1;
            
            while ((line = reader.readLine()) != null) {
                System.out.println("Line " + lineNumber + ": " + line);
                lineNumber++;
            }
            
            System.out.println("File reading complete");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了如何使用 BufferedReader 逐行读取文本文件。 try-with-resources 语句确保正确关闭 reader。 每次调用 readLine 都会返回下一行,不包含行终止字符。 这对于处理大型文本文件非常有效。

使用 BufferedReader 读取字符

BufferedReader 提供了读取单个字符或字符数组的方法。 read 方法在流的末尾返回 -1。 字符数组读取对于批量操作更有效。

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

public class Main {

    public static void main(String[] args) {
        try (BufferedReader reader = 
                new BufferedReader(new FileReader("data.txt"))) {
            
            // Read single character
            int charData;
            while ((charData = reader.read()) != -1) {
                System.out.print((char) charData);
            }
            
            System.out.println("\n\nReading complete");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了如何使用 BufferedReader 逐个字符地读取文件。 read 方法返回一个 int 以容纳 EOF 的 -1。 每次调用都可能从缓冲区而不是底层 Reader 获取数据。 为了获得更好的性能,请使用字符数组读取。

将字符读取到数组中

为了获得更好的性能,一次将多个字符读入字符数组。 这减少了方法调用和 I/O 操作。 read 方法返回实际读取的字符数。

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

public class Main {

    public static void main(String[] args) {
        try (BufferedReader reader = 
                new BufferedReader(new FileReader("largefile.txt"))) {
            
            char[] buffer = new char[1024];
            int charsRead;
            
            while ((charsRead = reader.read(buffer)) != -1) {
                System.out.println("Read " + charsRead + " characters");
                // Process the buffer data here
                String content = new String(buffer, 0, charsRead);
                System.out.print(content);
            }
            
            System.out.println("File reading complete");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例显示了批量读取到字符数组中。 缓冲区大小 (1024) 可以根据性能需要进行调整。 charsRead 值指示实际读取了多少字符。 这可能小于文件末尾的数组长度。 内容被转换为 String 以进行处理。

Mark 和 Reset 功能

BufferedReader 支持 mark 和 reset 操作以重新读取数据。 mark 方法标记当前位置,reset 返回到该位置。 readAheadLimit 参数指定在 mark 变为无效之前可以读取多少个字符。

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

public class Main {

    public static void main(String[] args) {
        String data = "BufferedReader mark/reset example";
        
        try (BufferedReader reader = new BufferedReader(new StringReader(data))) {
            
            // Read first 10 characters
            char[] firstPart = new char[10];
            reader.read(firstPart);
            System.out.println("First part: " + new String(firstPart));
            
            // Mark current position
            reader.mark(20); // Allow 20 chars to be read before mark invalid
            
            // Read next 10 characters
            char[] secondPart = new char[10];
            reader.read(secondPart);
            System.out.println("Second part: " + new String(secondPart));
            
            // Reset back to mark
            reader.reset();
            
            // Read again from marked position
            reader.read(secondPart);
            System.out.println("Second part after reset: " + new String(secondPart));
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了 mark 和 reset 功能。 在读取前 10 个字符后设置 mark。 在读取接下来的 10 个字符后,reset 返回到标记的位置。 readAheadLimit 为 20 意味着在标记后读取超过 20 个字符将使 mark 无效。

跳过流中的字符

skip 方法允许跳过流中指定数量的字符。 这比读取和丢弃数据更有效。 实际跳过的字符数可能少于请求的字符数。

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

public class Main {

    public static void main(String[] args) {
        String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        
        try (BufferedReader reader = new BufferedReader(new StringReader(data))) {
            
            System.out.println("Starting position");
            
            // Skip first 10 characters
            long skipped = reader.skip(10);
            System.out.println("Skipped " + skipped + " characters");
            
            // Read next character
            int nextChar = reader.read();
            System.out.println("Next character: " + (char) nextChar);
            
            // Skip beyond end of stream
            skipped = reader.skip(20);
            System.out.println("Skipped " + skipped + " characters (end approached)");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例显示了如何在 reader 中跳过字符。 第一个 skip 移动到前 10 个字母之后。 第二个 skip 尝试跳过 20 个字符,但只跳过剩余的字符。 skip 方法可用于忽略输入数据的某些部分。

来源

Java BufferedReader 类文档

在本文中,我们介绍了 Java BufferedReader 类的基本方法和功能。 理解这些概念对于在 Java 应用程序中使用高效的文本 I/O 操作至关重要。

作者

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

列出所有Java教程