Очень часто в программах есть требование быстро писать данные в файл или другие источники. И в таких случаях возникает вопрос: что использовать, какой класс выбрать? Сегодня мы познакомимся с одним из подходящих “кандидатов” на эту роль – классом BufferedWriter.

Для чего нужен BufferedWriter

BufferedWriter – это класс, записывающий буферизированные символы в поток. Он позволяет снизить количество данных, обращенных к физическому носителю. То есть, вместо того, чтобы каждый раз писать отдельный символ, он записывает эти данные в буфер, а после – записывает все эти символы в источник.

Это значительно увеличивает скорость записи данных. По умолчанию размер буфера равен 8192 символов, но этот показатель можно изменить, указав новый размер в конструкторе:


BufferedWriter(Writter in, int sz)

Здесь первый аргумент конструктора – это поток, приемник, в который будет происходить запись. А значение sz – это как раз определение нового размера буфера.

Также в Java еще есть класс BufferedReader: он используется для буферизованного чтения данных.

Собственно, что это такое – буфер? Давай разбираться на примере из жизни. Буфер — это как корзина или тележка в супермаркете. Вместо того, чтобы идти брать товар, нести на кассу, оплачивать, положить в багажник автомобиля и потом по новой возвращаться за другим, мы можем взять тележку, положить все, что нам нужно и оплатить на кассе. Именно так и работает буфер: он соберет твои данные и потом все возьмет и запишет, вместо того чтобы писать каждый фрагмент отдельно.

Конструкторы и методы класса BufferedWriter

Теперь давай подробнее разберем класс BufferedWriter. Для создания объекта есть два конструктора:


public BufferedWriter(Writer out) 
public BufferedWriter(Writer out, int sz)

Где out в обох конструкторах – это источник для записи, а sz, как уже упоминалось, – это размер буфера.

Также у класса BufferedWriter есть ряд методов. Часть из них сегодня рассмотрим подробнее:

write(char[] array) Запишет массив char в буфер
write(String s, int off, int len) Запишет часть строки в буфер
append(char c) Запишет символ в буфер
append(CharSequence csq, int start, int end) Запишет часть массива в буфер
newLine() Разделяет строку
flush() сбрасывает поток

Напишем программу, которая будет записывать нам значение в файл. В качестве объекта Writer в конструктор передадим FileWriter. Он используется для записи текстовых файлов и имеет несколько конструкторов для инициализации объектов:

FileWriter(File file)
FileWriter(File file, boolean append)
FileWriter(FileDescriptor fd)
FileWriter(String fileName)
FileWriter(String fileName, boolean append)

Для нашего примера используем конструктор, который принимает имя файла:


try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file.txt"))){
	
	String message = "Привет Амиго! Это очень важное сообщение!";
	bufferedWriter.write(message);
	bufferedWritter.flush();
}
catch(IOException ex){
System.out.println(ex.getMessage());
 }

Наш код, используя метод write(String str), запишет сообщения str в файл file.txt.

Есть другие методы для записи:

  • write(char[] array) – принимает и записывает массив char-ов;

  • write(String s, int off, int len) – принимает строку s, off – индекс символа строки, с которого начнется запись, и len – длина строки (подстроки), которая будет записана.


try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file.txt"))){
	String message = "Привет, Амиго! Это очень важное сообщение!";
	bufferedWriter.write(message, 0, 12);
 	bufferedWriter.flush();

}catch(IOException ex){
System.out.println(ex.getMessage());
}

Этот код запишет в файл: “Привет, Амиг”, так как мы указали записывать начиная с 0 индекса 12 символов.

В нашем коде еще присутствует try-with resources:


try(BufferedWriter bufferedWritter = new BufferedWriter(new FileWriter("file.txt"))) 

Это значит, что для моего объекта bufferedWriter метод close() вызывается автоматически, так как он реализует интерфейс AutoCloseable.

Метод flush() в коде используется для очистки выходного потока и записи всех буферизированных байтов. Без вызова этого метода запись может не произойти, так как он указывает, что нужно очистить буфер и записать байты из него.

Также в классе BufferedWriter есть такой метод как newLine(), который будет добавлять новую строку к нашему сообщению:


try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file.txt"))) {
        String message = "Привет, Амиго! Это очень важное сообщение!";
        bufferedWriter.write(message, 0, 14);
        bufferedWriter.newLine();
        bufferedWriter.write(message, 15, 27);
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }

В файле мы получим:

Привет, Амиго!
Это очень важное сообщение!

Сигнатура метода append() выглядит так:


public Writer append(CharSequence csq, int start, int end)

Используется для добавления csq. Здесь start – это индекс первого символа, а end – это индекс последнего символа строки (подстроки), которую нужно вставить, причем последний символ не будет вставлен.


try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file.txt"))) {
    String message = "Привет Амиго! Это очень важное сообщение!";
    bufferedWriter.append(message, 0, 7);
    bufferedWriter.flush();
} catch (IOException ex) {
    System.out.println(ex.getMessage());
}

Запустив этот код, ты получишь:

Привет

То есть методом append ты указываешь, какую часть строки добавить в буфер.

Если рассмотреть подробнее разницу между write() и append(), то в принципе они оба делают одну и ту же задачу: записывают значения.

Но все же разница заключается в том, что метод append более новый и принимает в аргумент CharSequence, а так как String — это реализация CharSequence, то в append можно положить и String, и StringBuilder, и StringBuffer. Ну а в метод write() можно только String.

Вот и все! Сегодня мы познакомились с буфером, с тем, как осуществлять буферизированную запись в файл, а также с методами, которыми ты можешь пользоваться для этого.