1. Копирование файлов
Метод Files.copy: базовый синтаксис
В Java для копирования файлов и папок используется статический метод Files.copy из пакета java.nio.file. Мы уже с ним сталкивались, но теперь изучим его подробнее. Базовый синтаксис Files.copy:
Files.copy(Path source, Path target, CopyOption... options)
- source — путь к исходному файлу или папке.
- target — путь, куда копировать.
- options — дополнительные опции (например, разрешить перезапись).
Простейший пример
Давайте скопируем файл "input.txt" из текущей директории в папку "backup" с именем "input_backup.txt":
import java.nio.file.*;
public class CopyExample {
public static void main(String[] args) throws Exception {
Path source = Path.of("input.txt");
Path target = Path.of("backup/input_backup.txt");
Files.copy(source, target);
System.out.println("Файл скопирован!");
}
}
Важные моменты:
- Если файл назначения уже существует, будет выброшено исключение FileAlreadyExistsException.
- Если папка "backup" не существует, метод выбросит ошибку — папка должна быть создана заранее!
Копирование с перезаписью
Чтобы разрешить перезапись файла, используйте опцию StandardCopyOption.REPLACE_EXISTING:
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Таблица: основные опции копирования
| Опция | Описание |
|---|---|
|
Перезаписывать файл, если он уже существует |
|
Копировать атрибуты (дата создания и т.п.) |
|
Атомарное перемещение (используется только с move) |
Копирование файла в другую папку
Перед копированием файла убедитесь, что папка-приёмник существует:
Path targetDir = Path.of("backup");
if (!Files.exists(targetDir)) {
Files.createDirectory(targetDir);
}
Files.copy(source, targetDir.resolve("input_backup.txt"), StandardCopyOption.REPLACE_EXISTING);
Копирование директорий: подвох
Метод Files.copy умеет копировать папки только как «пустую оболочку» — содержимое (файлы и подпапки) не копируется! Если вы попробуете скопировать папку с файлами, получите только пустую директорию. Для копирования целых директорий с содержимым потребуется рекурсивный обход и ручное копирование каждого файла (к этому ещё вернёмся в следующих лекциях).
Пример: копируем файл из одной папки в другую
Path source = Path.of("data/report.txt");
Path target = Path.of("backup/report.txt");
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Обработка ошибок при копировании
Копирование может завершиться неудачей по разным причинам: нет доступа, файл занят, не хватает места, файл уже есть и т.д. Лучше всегда использовать try-catch:
try {
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Копирование успешно!");
} catch (FileAlreadyExistsException e) {
System.out.println("Файл уже существует: " + target);
} catch (IOException e) {
System.out.println("Ошибка ввода-вывода: " + e.getMessage());
}
2. Перемещение файлов и папок
Метод Files.move: синтаксис
Перемещение файлов и папок выполняется с помощью метода:
Files.move(Path source, Path target, CopyOption... options)
Где source — путь к файлу (откуда двигаем), target — куда хотим положить файл или папку, options — дополнительные настройки (например, замена существующего файла).
Кстати, перемещение — это не только «переезд» файла, но и способ переименования (если меняется только имя). Ну а если файл с таким именем уже есть в целевой папке, будет выброшено исключение, если не указать опцию REPLACE_EXISTING.
Пример: перемещение файла в другую папку
Path source = Path.of("data/report.txt");
Path target = Path.of("archive/report.txt");
Files.move(source, target);
System.out.println("Файл перемещён!");
Перемещение с заменой существующего файла
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
Перемещение папки
Path oldDir = Path.of("data/old_reports");
Path newDir = Path.of("archive/old_reports");
Files.move(oldDir, newDir);
Вся папка, включая вложенные файлы и подпапки, переедет на новое место.
Но если в целевой папке уже есть папка с таким именем — получите ошибку.
Перемещение между разными файловыми системами
Если вы перемещаете файл между разными дисками (например, с "C:" на "D:"), под капотом произойдёт копирование с последующим удалением исходного файла. Если операция не поддерживается как атомарная, может быть выброшено исключение AtomicMoveNotSupportedException.
Отличие move от copy
- copy — исходный файл/папка остаётся на месте, появляется копия.
- move — исходный файл/папка исчезает, появляется только новый экземпляр.
3. Переименование файлов и папок
В Java нет отдельного метода «переименовать файл». Переименование — это частный случай перемещения: вы указываете новый путь с другим именем в той же директории.
Пример: переименование файла
Пусть у нас есть файл "report.txt", и мы хотим переименовать его в "report_old.txt" в той же папке:
Path dir = Path.of("data");
Path oldName = dir.resolve("report.txt");
Path newName = dir.resolve("report_old.txt");
Files.move(oldName, newName);
System.out.println("Файл переименован!");
Важные нюансы
Если в целевой директории уже существует файл или папка с тем именем, которое вы указываете, метод выбросит исключение. Чтобы обойти это ограничение и разрешить замену, можно использовать опцию StandardCopyOption.REPLACE_EXISTING.
Пример:
Path source = Paths.get("old_name.txt");
Path target = Paths.get("new_name.txt");
// Переименуем файл, если он уже есть — заменим
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
В этом примере файл "old_name.txt" будет переименован в "new_name.txt". Если в папке уже лежал файл с таким именем, он будет перезаписан.
Переименование папки
Path oldDir = Path.of("data/old_reports");
Path newDir = Path.of("data/archived_reports");
Files.move(oldDir, newDir);
System.out.println("Папка переименована!");
4. Обработка ошибок при копировании, перемещении и переименовании
Работа с файловой системой — это всегда риск неожиданных ситуаций. Вот самые частые проблемы:
Файл уже существует.
Исключение: FileAlreadyExistsException. Решение: используйте REPLACE_EXISTING, если хотите перезаписать.
Файл или папка заняты другим процессом.
Исключение: IOException. Например, файл открыт в другой программе.
Нет доступа к файлу или папке.
Исключение: AccessDeniedException. Проблема с правами пользователя.
Перемещение между разными файловыми системами.
Исключение: AtomicMoveNotSupportedException. Не все файловые системы поддерживают атомарное перемещение.
Целевая папка не существует.
Для копирования/перемещения убедитесь, что папка-приёмник создана заранее!
Пример обработки ошибок
try {
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
} catch (FileAlreadyExistsException e) {
System.out.println("Файл назначения уже существует: " + target);
} catch (AtomicMoveNotSupportedException e) {
System.out.println("Атомарное перемещение не поддерживается: " + e.getMessage());
} catch (IOException e) {
System.out.println("Ошибка при перемещении: " + e.getMessage());
}
5. Практические рекомендации
Проверка существования целевого файла/папки
Перед копированием или перемещением всегда полезно проверить, не занят ли путь назначения:
if (Files.exists(target)) {
System.out.println("Файл уже есть, не будем перезаписывать.");
} else {
Files.copy(source, target);
}
Использование временных файлов для безопасных операций
При сложных операциях (например, обновление важных файлов) часто используют временные файлы — сначала копируют во временный файл, а потом заменяют основной:
Path temp = Path.of("data/report.tmp");
Files.copy(source, temp, StandardCopyOption.REPLACE_EXISTING);
Files.move(temp, target, StandardCopyOption.REPLACE_EXISTING);
Такой подход минимизирует риск потери данных при сбоях.
Пример: резервное копирование файла перед заменой
Path file = Path.of("data/report.txt");
Path backup = Path.of("data/report_backup.txt");
if (Files.exists(file)) {
Files.copy(file, backup, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Резервная копия создана.");
}
6. Таблица: основные методы и опции
| Операция | Метод Java NIO | Особенности |
|---|---|---|
| Копирование | |
Не копирует содержимое папок! |
| Перемещение | |
Можно использовать для переименования |
| Переименование | |
Новый путь в той же директории |
| Перезапись | |
Перезаписывает файл/папку назначения |
| Проверка | |
Проверяет существование файла/папки |
7. Типичные ошибки при копировании, перемещении и переименовании файлов
Ошибка №1: попытка скопировать файл в несуществующую папку. Если целевая директория не создана, получите NoSuchFileException. Решение: создавать папку заранее с помощью Files.createDirectories.
Ошибка №2: попытка скопировать папку целиком с помощью Files.copy. Метод скопирует только «пустую оболочку», а не содержимое. Для полного копирования нужен рекурсивный обход.
Ошибка №3: отсутствие обработки существующего файла. Если не передать REPLACE_EXISTING, а файл уже есть, будет выброшено исключение. Лучше явно обрабатывать этот случай.
Ошибка №4: попытка переименовать файл, когда файл с новым именем уже существует. Аналогично, получите FileAlreadyExistsException. Перед переименованием можно проверить наличие файла.
Ошибка №5: перемещение между разными файловыми системами. Иногда операция не поддерживается «атомарно» и выбрасывается AtomicMoveNotSupportedException. В этом случае используйте обычное перемещение без атомарности.
Ошибка №6: отсутствие прав доступа или блокировка файла. Если файл открыт в другой программе или нет прав на запись/чтение, получите AccessDeniedException или IOException. Всегда обрабатывайте такие исключения.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ