BufferedReader

Класс java.io.BufferedReader оборачивает любой Reader и добавляет к нему буферизацию — вместо чтения по одному символу из подлежащего потока, BufferedReader забирает целыми блоками. Это резко ускоряет работу при чтении из файлов и сетевых сокетов.

Главная «фишка» — метод readLine(), который возвращает строку без символа перевода строки или null по достижении конца потока. Это удобный идиоматический способ перебирать текстовые файлы построчно.

Под капотом часто используется связка FileReader BufferedReader (для файлов) или InputStreamReader BufferedReader (когда нужно явно указать кодировку или читать System.in).

Синтаксис

import java.io.*;

try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        // обработка
    }
}

Пример 1. Построчное чтение файла

import java.io.*;
import java.nio.file.*;

public class ReadLines {
    public static void main(String[] args) throws IOException {
        Path p = Paths.get("sensors.log");
        Files.writeString(p, "DHT22 22.5\nDHT22 22.7\nBMP280 23.1\n");

        try (BufferedReader br = new BufferedReader(new FileReader(p.toFile()))) {
            String line;
            int n = 1;
            while ((line = br.readLine()) != null) {
                System.out.println(n++ + ": " + line);
            }
        }
        Files.delete(p);
    }
}

Output:

1: DHT22 22.5
2: DHT22 22.7
3: BMP280 23.1

Пример 2. Подсчёт строк и слов

import java.io.*;
import java.nio.file.*;

public class WordCount {
    public static void main(String[] args) throws IOException {
        Path p = Paths.get("doc.txt");
        Files.writeString(p, "Hello world\nJava IO\nAlashEd wiki\n");

        int lines = 0, words = 0;
        try (BufferedReader br = new BufferedReader(new FileReader(p.toFile()))) {
            String line;
            while ((line = br.readLine()) != null) {
                lines++;
                if (!line.isEmpty()) words += line.split("\\s+").length;
            }
        }
        System.out.println("Строк: " + lines);
        System.out.println("Слов:  " + words);
        Files.delete(p);
    }
}

Output:

Строк: 3
Слов:  6

Пример 3. Чтение из System.in

import java.io.*;

public class ReadFromConsole {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("Имя датчика: ");
        String name = br.readLine();
        System.out.print("Пин: ");
        int pin = Integer.parseInt(br.readLine());
        System.out.println("OK: " + name + " на " + pin);
    }
}

Ввод/Output:

Имя датчика: DHT22
Пин: 7
OK: DHT22 на 7

Пример 4. Парсинг CSV-лога датчиков

import java.io.*;
import java.nio.file.*;

public class CsvParser {
    public static void main(String[] args) throws IOException {
        Path p = Paths.get("log.csv");
        Files.writeString(p, "sensor,temp\nDHT22,22.5\nBMP280,23.1\nDHT22,22.7\n");

        double sum = 0;
        int    cnt = 0;
        try (BufferedReader br = new BufferedReader(new FileReader(p.toFile()))) {
            br.readLine();                         // пропускаем заголовок
            String line;
            while ((line = br.readLine()) != null) {
                String[] parts = line.split(",");
                sum += Double.parseDouble(parts[1]);
                cnt++;
            }
        }
        System.out.printf("Среднее: %.2f (по %d записям)%n", sum / cnt, cnt);
        Files.delete(p);
    }
}

Output:

Среднее: 22.77 (по 3 записям)

Пример 5. Чтение с указанием кодировки

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

public class EncodingDemo {
    public static void main(String[] args) throws IOException {
        Path p = Paths.get("ru.txt");
        Files.writeString(p, "Привет, AlashEd\n", StandardCharsets.UTF_8);

        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(new FileInputStream(p.toFile()),
                                      StandardCharsets.UTF_8))) {
            System.out.println(br.readLine());
        }
        Files.delete(p);
    }
}

Output:

Привет, AlashEd

Пример 6. Stream API через lines()

import java.io.*;
import java.nio.file.*;

public class LinesStream {
    public static void main(String[] args) throws IOException {
        Path p = Paths.get("nums.txt");
        Files.writeString(p, "1\n2\n3\n4\n5\n");

        int sum;
        try (BufferedReader br = new BufferedReader(new FileReader(p.toFile()))) {
            sum = br.lines()
                    .mapToInt(Integer::parseInt)
                    .sum();
        }
        System.out.println("Сумма: " + sum);
        Files.delete(p);
    }
}

Output:

Сумма: 15

Подводные камни

Предупреждение

  • ``readLine()`` возвращает ``null`` в конце потока — не путать с пустой строкой "".

  • Без try-with-resources легко забыть закрыть — буфер не сбросится в подлежащий поток (актуально для BufferedWriter).

  • Без явной кодировки FileReader использует системную, что ломает русский текст на старых JDK. Используйте InputStreamReader с StandardCharsets.UTF_8.

  • ``BufferedReader`` не потокобезопасен — не делите между потоками без синхронизации.

  • ``br.lines()`` возвращает Stream, который держит ресурс открытым — используйте try-with-resources на самом BufferedReader.

См. также

Примечание

Материал подготовлен на основе официальной документации Oracle Java Tutorials — Buffered Streams и Character Streams (Oracle Free Documentation License). Текст переведён и переработан, примеры кода написаны заново.