BufferedReader и
BufferedWriter это классы-обертки из пакета
java.io, которые добавляют буфер к символьным потокам чтения и записи. Вместо обращения к диску на каждый символ они копят данные в памяти и работают с диском большими порциями. Попутно
BufferedReader дает метод
readLine() для чтения строки целиком, а
BufferedWriter метод
newLine() для переноса строки.
Кратко
- Оба класса это обертки:
BufferedReader оборачивает Reader, BufferedWriter оборачивает Writer. - Смысл буфера в скорости: данные копятся в памяти и уходят на диск большими порциями, а не по одному символу.
- Размер буфера задают вторым параметром конструктора, иначе берется размер по умолчанию.
readLine() возвращает очередную строку или null в конце потока, поэтому его ставят условием цикла while.BufferedWriter не пишет на диск сразу: данные уходят при заполнении буфера, а также при вызове flush() или close().- Открывать оба класса удобнее в
try-with-resources: поток закроется сам, даже если возникнет исключение.
BufferedReader
Java класс
BufferedReader читает текст из потока ввода символов, буферизуя прочитанные символы, чтобы обеспечить эффективное считывание символов, массивов и строк. Можно указать в конструкторе вторым параметром размер буфера.
Конструкторы BufferedReader
У класса два конструктора:
BufferedReader(Reader in)
BufferedReader(Reader in, int sz)
Методы BufferedReader
Методы класса:
close()
mark(int readAheadLimit)
markSupported()
int read()
int read(char[] cbuf, int off, int len)
String readLine()
boolean ready()
reset()
skip(long n)
С Java 8 у
BufferedReader есть еще один метод,
lines(): он возвращает все строки потока как
Stream<String>, и файл можно обработать без цикла
while.
Пример: чтение файла
Чтение файла построчно:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
String inputFileName = "file.txt";
try (BufferedReader reader = new BufferedReader(new FileReader(inputFileName))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line + "\n");
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedWriter
Java класс
BufferedWriter записывает текст в поток вывода символов, буферизуя записанные символы, чтобы обеспечить эффективную запись символов, массивов и строк. Можно указать в конструкторе вторым параметром размер буфера.
Конструкторы BufferedWriter
У класса тоже два конструктора:
BufferedWriter(Writer out)
BufferedWriter(Writer out, int sz)
Методы BufferedWriter
Методы класса:
close()
flush()
newLine()
write(char[] cbuf, int off, int len)
write(int c)
write(String s, int off, int len)
Пример: запись в файл
Запись массива строк в файл:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class FileWritterExample {
public static void main(String[] args) {
String outputFileName = "file.txt";
String[] array = { "one", "two", "three", "four" };
try (BufferedWriter writter = new BufferedWriter(new FileWriter(outputFileName))) {
for (String value : array) {
writter.write(value + "\n");
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter сразу записывает данные на диск и каждый раз к нему обращается, а буфер работает как обертка и ускоряет работу приложения. Буфер накапливает данные в себе, а потом большим куском сбрасывает их на диск. Так же устроены и
буферизованные байтовые потоки.
Считываем данные с консоли и записываем в файл
Соединим оба класса в одной программе: будем читать
ввод с клавиатуры и писать его в файл, пока не встретим строку exit.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
public class ConsoleReaderExample {
public static void main(String[] args) {
String outputFileName = "file.txt";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
try (BufferedWriter writter = new BufferedWriter(new FileWriter(outputFileName))) {
String line;
while (!(line = reader.readLine()).equals("exit")) {
writter.write(line);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Вопросы и ответы
Зачем оборачивать FileReader в BufferedReader?
FileReader обращается к диску на каждое чтение, а это медленно. BufferedReader накапливает данные в буфере в памяти и читает с диска большими порциями. Плюс он добавляет метод readLine(), которого у FileReader нет.
Что возвращает readLine(), когда файл закончился?
null. Именно поэтому его удобно ставить условием цикла: while ((line = reader.readLine()) != null). Пустая строка внутри файла вернется как пустая строка, а не как null.
Почему данные не появляются в файле сразу после write()?
Потому что BufferedWriter держит их в буфере. На диск они уходят, когда буфер заполнится, либо при вызове flush() или close(). Если поток не закрыть, часть данных может пропасть.
Как задать свой размер буфера?
Вторым параметром конструктора: new BufferedReader(reader, 16384) или new BufferedWriter(writer, 16384). Если параметр не указан, берется размер по умолчанию.
Нужно ли закрывать BufferedReader и BufferedWriter вручную?
Закрывать нужно обязательно, но вручную не обязательно. Если создать поток в круглых скобках try-with-resources, как в примерах выше, он закроется сам, даже когда возникнет исключение.
Как читать ввод с консоли через BufferedReader?
Обернуть System.in в InputStreamReader, а его в BufferedReader: new BufferedReader(new InputStreamReader(System.in)). Дальше readLine() возвращает то, что пользователь ввел и подтвердил клавишей Enter.
Источник:
Oracle: класс BufferedReader.
Читайте также