Работа с файлами в Java: учебные примеры для школьника
💻 Информатика · 10 класс
Чтение и запись файлов в школьном проекте Java17: Path, Files, UTF-8, APPEND, копирование и IOException. Примеры, пять заданий и программа с закрытием потока.

В учебной программе на Java файл может хранить заметки школьника или результаты небольшого проекта. Для работы с ним удобно использовать пакет java.nio.file: Path — интерфейс, описывающий путь, а Files — класс со статическими операциями. Пакет появился в Java 7, но здесь примеры рассчитаны на Java 17: методы readString, writeString и isBlank доступны с Java 11. Разберём чтение, запись, копирование и обработку ошибок на небольших текстовых файлах.
Path: как адресовать файл
Короткие фрагменты ниже показывают отдельные операции, а не одну последовательную программу. Нужны импорты java.nio.file.Path, Paths, Files, StandardOpenOption, StandardCopyOption, java.io.IOException и java.util.List по мере использования. Переменные dir, copyPath и newPath должны содержать нужные вам пути. Полная программа с импортами приведена в конце.
Path file = Paths.get("data", "notes.txt");
Path abs = file.toAbsolutePath();Paths.get собирает путь из сегментов по правилам файловой системы. При стандартном провайдере Windows разделитель обычно обратный слэш, а в Linux и macOS — прямой. Относительный путь data/notes.txt ищется относительно рабочего каталога программы, который не обязан совпадать с папкой исходного Java-файла. Путь — ещё не файл: он описывает адрес, а существование проверяют отдельно.
Чтение файла
Самые частые приёмы — прочитать файл целиком строкой или списком строк:
String text = Files.readString(file); // Java 11+
List<String> lines = Files.readAllLines(file); // список строкПример 1. Подсчёт строк с непробельными символами. Файл notes.txt содержит четыре строки, одна из них пустая:
List<String> lines = Files.readAllLines(file);
int count = 0;
for (String s : lines) {
if (!s.isBlank()) count++;
}
System.out.println(count); // 3Из четырёх строк («молоко», «хлеб», пустая, «масло») условию соответствуют три. isBlank также считает пустой для этой проверки строку, состоящую только из пробельных символов по правилам Java, например пробелов и табуляции. Методы readString и readAllLines без параметра кодировки используют UTF-8; при другой кодировке её нужно указать явно. Для очень больших файлов чтение целиком расточительно — там используют потоки (BufferedReader) или Files.lines(file), который отдаёт строки лениво. Поток Files.lines удерживает открытый файл: его нужно закрыть, например через try-with-resources. Это показано в полной программе ниже.
Запись и перезапись
Пример 2. Запись строки и чтение обратно.
Path out = Paths.get("out.txt");
Files.writeString(out, "привет, файл!\n"); // создаст или перезапишет
String back = Files.readString(out);
System.out.print(back); // привет, файл! и перевод строкиМетод writeString создаёт файл, если его нет, и перезаписывает содержимое, если есть. Чтобы дописывать в конец, указывают опцию: Files.writeString(out, "ещё\n", StandardOpenOption.APPEND). Если файл может отсутствовать, добавьте CREATE: Files.writeString(out, "ещё\n", StandardOpenOption.CREATE, StandardOpenOption.APPEND). Только APPEND не обещает создать отсутствующий файл. Для списка строк служит Files.write(out, lines): разделители строк добавляются по правилам платформы. Родительские каталоги сами не создаются при записи; для них можно заранее вызвать Files.createDirectories.
Проверка, копирование, перемещение, удаление
Files.exists(file); // файл есть?
Files.notExists(file); // файла точно нет?
Files.createFile(file); // создать пустой (бросит ошибку, если существует)
Files.createDirectory(dir); // создать каталог
Files.copy(file, copyPath); // копия
Files.copy(file, copyPath, StandardCopyOption.REPLACE_EXISTING); // копия с заменой
Files.move(file, newPath, StandardCopyOption.REPLACE_EXISTING); // переименование/перемещение
Files.delete(file); // удалить (ошибка, если файла нет)В примере с копией видно важное различие: без опции REPLACE_EXISTING копирование в существующий файл завершится ошибкой, а с опцией — молча заменит целевой файл. Это правило для обычных разных файлов. Копирование файла в самого себя имеет отдельную семантику, а замена не означает возможность перезаписать непустой каталог. Методы exists и notExists не являются точными отрицаниями друг друга: если существование нельзя определить, оба могут вернуть false. Проверка существования также не гарантирует успех последующей операции — состояние могло измениться.
Обязательная обработка IOException
Чтение, запись, копирование и многие другие операции Files объявляют проверяемое исключение IOException, но не каждый метод пакета: например, exists и notExists его не объявляют. Причины ошибок бывают разными: файл могут удалить между проверкой и чтением, диск может быть переполнен. Поэтому код оборачивают в try-catch (подробный разбор конструкции — в нашем материале о try, catch и finally в Java):
try {
String text = Files.readString(file);
System.out.println(text.length());
} catch (IOException e) {
System.err.println("Не удалось прочитать файл: " + e.getMessage());
}В учебных задачах часто пишут throws IOException в сигнатуре main — это допустимо, но неперехваченное исключение завершит выполнение main; устойчивый код различает ситуации через catch.
Упражнения
Задание 1
Как прочитать весь текстовый файл в одну строку современным API?
Ответ 1: Files.readString(path) — метод пакета java.nio.file, доступен с Java 11; для списка строк используют Files.readAllLines.
Задание 2
Файл содержит строки «молоко», «хлеб», пустую строку и «масло». Что выведет пример 1?
Ответ 2: 3: цикл считает строки, для которых isBlank() ложно, а для пустой строки isBlank() истинно. Строка из одних пробелов или табуляций тоже не увеличит счётчик.
Задание 3
Чем отличается Files.copy(a, b) от Files.copy(a, b, REPLACE_EXISTING)?
Ответ 3: для обычных разных файлов без замены существующий b не перезаписывается; с StandardCopyOption.REPLACE_EXISTING замена разрешена. В API FileAlreadyExistsException обозначена как необязательное специфическое исключение: переносимый код должен учитывать и IOException. Само копирование не является атомарной операцией.
Задание 4
Почему компилятор требует try-catch вокруг Files.readString, а вокруг System.out.println — нет?
Ответ 4: readString объявляет проверяемое IOException — его надо поймать или пробросить через throws; println таких исключений не объявляет. Различие зафиксировано в сигнатурах методов.
Задание 5
Как дописать строку «ещё» в конец существующего файла out.txt, не стирая прежнее содержимое?
Ответ 5: Files.writeString(path, "ещё\n", StandardOpenOption.APPEND) — опция APPEND переводит запись в режим дописывания; без неё файл был бы перезаписан.
Полная учебная программа
Сохраните код в Notes.java и запускайте из отдельной учебной папки: javac Notes.java, затем java Notes. Пример создаёт каталог school-file-demo и создаёт или перезаписывает в нём notes.txt. Он выводит 3 и закрывает поток чтения после подсчёта.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class Notes {
public static void main(String[] args) {
try {
Path dir = Path.of("school-file-demo");
Files.createDirectories(dir);
Path file = dir.resolve("notes.txt");
Files.writeString(file, "молоко\nхлеб\n\nмасло\n",
StandardCharsets.UTF_8);
long count;
try (Stream<String> lines = Files.lines(file, StandardCharsets.UTF_8)) {
count = lines.filter(line -> !line.isBlank()).count();
}
System.out.println(count); // 3
} catch (IOException e) {
System.err.println("Ошибка работы с файлом: " + e.getMessage());
}
}
}