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). Текст переведён и переработан, примеры кода написаны заново.