FileWriter: примеры (JAVA)
FileWriter(File file, String fileName, boolean append)Общее описание FileWriter в Java
Класс FileWriter служит для записи символьных данных в файл. Он является подклассом java.io.OutputStreamWriter и ориентирован на простую запись текста с использованием кодировки по умолчанию платформы. Обычно применяется для быстрого создания или дозаписи текстовых файлов, когда не требуется явная установка кодировки или буферизация.
Конструкторы и их параметры:
FileWriter(String fileName)- открывает файл по имени; если файл не существует, создаётся; если существует, содержимое перезаписывается. Параметр:fileName(не null). Может броситьIOExceptionилиNullPointerException.FileWriter(String fileName, boolean append)- второй параметрappendуказывает дозапись в конец файла (true) или перезапись (false).FileWriter(File file)- аналогично первому, принимает объектFile.FileWriter(File file, boolean append)- вариант с флагом дозаписи.FileWriter(FileDescriptor fd)- создаёт писатель из уже открытого файлового дескриптора; полезно при работе с нативными дескрипторами.
Основные методы (наследуемые/реализуемые) и их поведение:
void write(int c)- записать один символ (целое значение символа).void write(char[] cbuf)- записать массив символов.void write(char[] cbuf, int off, int len)- записать часть массива с смещением и длиной.void write(String str)- записать всю строку.void write(String str, int off, int len)- записать часть строки.Writer append(CharSequence csq)- реализует интерфейсAppendable, возвращает тот же объект писателя для цепочек вызовов.Writer append(CharSequence csq, int start, int end)иWriter append(char c)- дополнительные перегрузки.void flush()- сбрасывает буферы в ОС; полезно для гарантии сохранения данных до закрытия.void close()- закрывает поток; после закрытия дальнейшие операции вызывают исключение.
Возвращаемые значения: методы записи и закрытия имеют тип void, методы append возвращают ссылку на Writer (обычно сам FileWriter) для удобства построения цепочек.
Исключения и особенности:
- Конструкторы и методы записи бросают
IOExceptionпри проблемах с файловой системой. - FileWriter использует кодировку по умолчанию платформы; при необходимости конкретной кодировки следует применять
OutputStreamWriterс указаниемCharsetили использовать APIFiles.newBufferedWriter. - Класс не обеспечивает внутренней синхронизации; многопоточный доступ требует внешней синхронизации.
- Для повышения производительности часто оборачивается в
BufferedWriterилиPrintWriter.
Короткие примеры использования FileWriter
Пример 1. Простая запись строки (перезапись файла).
import java.io.FileWriter;
import java.io.IOException;
public class Example1 {
public static void main(String[] args) throws IOException {
try (FileWriter fw = new FileWriter("out1.txt")) {
fw.write("Привет, FileWriter!\n");
}
}
}
Результат: файл out1.txt содержит текст "Привет, FileWriter!" и перевод строки.
Пример 2. Дозапись в существующий файл.
try (FileWriter fw = new FileWriter("out1.txt", true)) {
fw.write("Дополнительная строка\n");
}
Результат: в конце out1.txt добавлена строка "Дополнительная строка".
Пример 3. Запись подмножества символов и строки.
try (FileWriter fw = new FileWriter("out2.txt")) {
char[] arr = {'а','б','в','г','д'};
fw.write(arr, 1, 3); // запишет 'бвг'
fw.write("12345", 1, 3); // запишет '234'
}
Результат: out2.txt содержит "бвг234".
Пример 4. Использование FileDescriptor (встроенный дескриптор).
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileWriter;
try (FileOutputStream fos = new FileOutputStream("out3.txt")) {
FileDescriptor fd = fos.getFD();
try (FileWriter fw = new FileWriter(fd)) {
fw.write("Запись через FileDescriptor\n");
}
}
Результат: out3.txt содержит строку "Запись через FileDescriptor".
Альтернативы внутри Java и их особенности
- BufferedWriter - оборачивается вокруг Writer (включая FileWriter) для буферизации; повышает производительность при множественных мелких записях.
- OutputStreamWriter (в комбинации с FileOutputStream) - позволяет явно указать кодировку, тогда как FileWriter использует кодировку по умолчанию.
- PrintWriter - удобен для форматированного вывода (методы
print/printf/println); предоставляет опцию автосброса при необходимости. - java.nio.file.Files.newBufferedWriter - современный NIO API с возможностью указать Charset и опции открытия файла; предпочтителен при работе с NIO.
- Files.write - удобен для однократной записи небольших массивов байтов/строк; выполняет всю операцию в один вызов.
Когда отдавать предпочтение:
- Если нужна явная кодировка -
OutputStreamWriterилиFiles.newBufferedWriter. - При большом объёме операций записи - оборачивать в
BufferedWriter. - Для форматированного вывода -
PrintWriter. - Для единоразовой записи небольших наборов данных -
Files.write.
Аналоги в других языках и краткие примеры
PHP
// file_put_contents
file_put_contents('php_out.txt', "Привет из PHP\n");
Результат: php_out.txt содержит строку "Привет из PHP".
JavaScript (Node.js)
// синхронная запись
const fs = require('fs');
fs.writeFileSync('node_out.txt', 'Привет из Node\n', 'utf8');
Результат: node_out.txt содержит "Привет из Node".
Python
# с указанием кодировки
with open('py_out.txt', 'w', encoding='utf-8') as f:
f.write('Привет из Python\n')
Результат: py_out.txt содержит "Привет из Python".
C#
using System.IO;
File.WriteAllText("cs_out.txt", "Привет из C#\n");
Результат: cs_out.txt содержит "Привет из C#".
Go
package main
import (
"os"
)
func main() {
os.WriteFile("go_out.txt", []byte("Привет из Go\n"), 0644)
}
Результат: go_out.txt содержит "Привет из Go".
Lua
local f = io.open('lua_out.txt', 'w')
f:write('Привет из Lua\n')
f:close()
Результат: lua_out.txt содержит "Привет из Lua".
Kotlin
import java.io.File
File("kt_out.txt").writeText("Привет из Kotlin\n")
Результат: kt_out.txt содержит "Привет из Kotlin".
SQL
Прямых аналогов записи файла в SQL нет; обычно экспорт выполняется через утилиты СУБД (COPY в PostgreSQL) или с использованием языков хостинга (см. примеры выше).
Типичные ошибки при работе с FileWriter
1. NullPointerException при передаче null в конструктор.
new FileWriter((String) null);
Исключение: java.lang.NullPointerException
2. IOException при попытке открыть директорию или при отсутствии прав.
try (FileWriter fw = new FileWriter("/etc")) {
fw.write("test");
}
Исключение: java.io.IOException: Is a directory (или сообщение ОС: "Access is denied")
3. PermissionDenied при отсутствии прав на запись.
// запуск в защищённой папке
try (FileWriter fw = new FileWriter("C:\\Windows\\system32\\file.txt")) {
fw.write("x");
}
Исключение: java.io.IOException: Permission denied (в Unix) или Access is denied (в Windows)
4. Потеря специфичной кодировки при использовании FileWriter.
try (FileWriter fw = new FileWriter("utf_out.txt")) {
fw.write("текст с символами € и другие\n");
}
Результат: возможно некорректное отображение символов, если кодировка по умолчанию не поддерживает эти символы. Рекомендуется явное задание Charset.
5. Неэффективность при частых мелких операциях записи без буфера.
for (int i = 0; i < 10000; i++) fw.write("a");
Результат: медленная работа; рекомендация - использовать BufferedWriter.
Изменения и рекомендации по использованию в последних версиях Java
Класс FileWriter не подвергался существенным изменениям в последних релизах; его поведение сохраняет совместимость. Основные тенденции платформы следующие:
- Рекомендуется применять NIO API (
java.nio.file.Files) и явное указаниеCharsetдля избежания проблем с кодировками. - При возможности предпочтение отдаётся
Files.newBufferedWriterилиFiles.writeдля более явного управления опциями открытия файла. - Поддержка try-with-resources (начиная с Java 7) делает управление ресурсами более безопасным.
Расширенные и редкие сценарии применения FileWriter
Пример 1. Буферизированная запись большого файла с прогрессом.
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BigWrite {
public static void main(String[] args) throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("big.txt"), 16 * 1024)) {
for (int i = 0; i < 500_000; i++) {
bw.write("Строка номер " + i + "\n");
if (i % 100_000 == 0) {
System.out.println("Прогресс: " + i);
}
}
}
}
}
Результат: файл big.txt содержит 500000 строк; в консоль выводятся стадии прогресса (0, 100000, 200000...).
Пример 2. Атомарическая замена файла через временный файл.
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Path target = Path.of("atomic.txt");
Path temp = Files.createTempFile(target.getParent(), "tmp", ".tmp");
try (FileWriter fw = new FileWriter(temp.toFile())) {
fw.write("Новый содержимый файл\n");
}
Files.move(temp, target, java.nio.file.StandardCopyOption.REPLACE_EXISTING, java.nio.file.StandardCopyOption.ATOMIC_MOVE);
Результат: файл atomic.txt заменяется атомарно новым содержимым, минимизируется время, когда файла нет или он частично записан.
Пример 3. Запись через GZIP с текстовой кодировкой (сжатая текстовая логика).
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.zip.GZIPOutputStream;
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream("log.txt.gz")), java.nio.charset.StandardCharsets.UTF_8))) {
bw.write("Сжатый лог\n");
}
Результат: создаётся сжатый файл log.txt.gz, содержащий текст в кодировке UTF-8.
Пример 4. Совместная запись с блокировкой файла (FileLock).
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
try (FileOutputStream fos = new FileOutputStream("locked.txt", true);
FileChannel ch = fos.getChannel();
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
try (FileLock lock = ch.lock()) { // блокировка на время записи
osw.write("Запись с блокировкой\n");
osw.flush();
}
}
Результат: запись добавляется с полученной эксклюзивной блокировкой файла, снижая риск конфликтов в многопроцессной среде.
Пример 5. Обход ограничений кодировки: использование OutputStreamWriter вместо FileWriter.
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("utf8.txt"), StandardCharsets.UTF_8))) {
bw.write("Текст с символами € и эмодзи ????\n");
}
Результат: utf8.txt корректно содержит специфичные символы в UTF-8, в отличие от FileWriter при неподходящей системной кодировке.