Дуже часто у програмах є вимога швидко писати дані у файл чи інші джерела. І в таких випадках постає питання: що використати, який клас обрати? Сьогодні ми познайомимося з одним із придатних “кандидатів” на цю роль – класом 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, запише повідомлення 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.

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