1. Kopiowanie plików
Metoda Files.copy: podstawowa składnia
W Javie do kopiowania plików i folderów używa się metody statycznej Files.copy z pakietu java.nio.file. Już się z nią spotkaliśmy, ale teraz omówimy ją dokładniej. Podstawowa składnia Files.copy:
Files.copy(Path source, Path target, CopyOption... options)
- source — ścieżka do pliku lub folderu źródłowego.
- target — ścieżka docelowa, dokąd kopiować.
- options — dodatkowe opcje (np. zezwolenie na nadpisanie).
Najprostszy przykład
Skopiujmy plik "input.txt" z bieżącego katalogu do folderu "backup" pod nazwą "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("Plik został skopiowany!");
}
}
Ważne uwagi:
- Jeśli plik docelowy już istnieje, zostanie zgłoszony wyjątek FileAlreadyExistsException.
- Jeśli folder "backup" nie istnieje, metoda zgłosi błąd — folder musi zostać utworzony wcześniej!
Kopiowanie z nadpisaniem
Aby zezwolić na nadpisanie pliku, użyj opcji StandardCopyOption.REPLACE_EXISTING:
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Tabela: najważniejsze opcje kopiowania
| Opcja | Opis |
|---|---|
|
Nadpisuje plik, jeśli już istnieje |
|
Kopiuje atrybuty (data utworzenia itp.) |
|
Przeniesienie atomowe (używane tylko z move) |
Kopiowanie pliku do innego folderu
Przed skopiowaniem pliku upewnij się, że folder docelowy istnieje:
Path targetDir = Path.of("backup");
if (!Files.exists(targetDir)) {
Files.createDirectory(targetDir);
}
Files.copy(source, targetDir.resolve("input_backup.txt"), StandardCopyOption.REPLACE_EXISTING);
Kopiowanie katalogów: pułapka
Metoda Files.copy potrafi kopiować foldery jedynie jako „pustą skorupę” — zawartość (pliki i podfoldery) nie jest kopiowana! Jeśli spróbujesz skopiować folder z plikami, otrzymasz tylko pusty katalog. Aby skopiować całe katalogi wraz z zawartością, potrzebny jest rekursywny przebieg i ręczne kopiowanie każdego pliku (wrócimy do tego w kolejnych wykładach).
Przykład: kopiujemy plik z jednego folderu do innego
Path source = Path.of("data/report.txt");
Path target = Path.of("backup/report.txt");
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Obsługa błędów przy kopiowaniu
Kopiowanie może się nie powieść z różnych powodów: brak dostępu, plik zajęty, za mało miejsca, plik już istnieje itd. Najlepiej zawsze używać try-catch:
try {
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Kopiowanie zakończone powodzeniem!");
} catch (FileAlreadyExistsException e) {
System.out.println("Plik już istnieje: " + target);
} catch (IOException e) {
System.out.println("Błąd wejścia/wyjścia: " + e.getMessage());
}
2. Przenoszenie plików i folderów
Metoda Files.move: składnia
Przenoszenie plików i folderów wykonuje się za pomocą metody:
Files.move(Path source, Path target, CopyOption... options)
Gdzie source — ścieżka do pliku (skąd przenosimy), target — dokąd chcemy umieścić plik lub folder, options — dodatkowe ustawienia (np. zastąpienie istniejącego pliku).
Przy okazji, przeniesienie to nie tylko „przeprowadzka” pliku, lecz także sposób na zmianę nazwy (jeśli zmienia się tylko nazwa). A jeśli w folderze docelowym istnieje już plik o tej nazwie, zostanie zgłoszony wyjątek, jeśli nie podasz opcji REPLACE_EXISTING.
Przykład: przeniesienie pliku do innego folderu
Path source = Path.of("data/report.txt");
Path target = Path.of("archive/report.txt");
Files.move(source, target);
System.out.println("Plik przeniesiono!");
Przenoszenie z zastąpieniem istniejącego pliku
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
Przenoszenie folderu
Path oldDir = Path.of("data/old_reports");
Path newDir = Path.of("archive/old_reports");
Files.move(oldDir, newDir);
Cały folder, łącznie z plikami i podfolderami, trafi w nowe miejsce.
Ale jeśli w folderze docelowym istnieje już folder o takiej nazwie — otrzymasz błąd.
Przenoszenie między różnymi systemami plików
Jeśli przenosisz plik między różnymi dyskami (np. z "C:" na "D:"), pod spodem nastąpi skopiowanie, a następnie usunięcie pliku źródłowego. Jeśli operacja nie jest wspierana jako atomowa, może zostać zgłoszony wyjątek AtomicMoveNotSupportedException.
Różnica między move a copy
- copy — plik/folder źródłowy pozostaje na miejscu, pojawia się kopia.
- move — plik/folder źródłowy znika, pozostaje tylko nowy egzemplarz.
3. Zmienianie nazw plików i folderów
W Javie nie ma osobnej metody „zmień nazwę pliku”. Zmiana nazwy to szczególny przypadek przeniesienia: podajesz nową ścieżkę z inną nazwą w tym samym katalogu.
Przykład: zmiana nazwy pliku
Załóżmy, że mamy plik "report.txt" i chcemy zmienić jego nazwę na "report_old.txt" w tym samym folderze:
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("Zmieniono nazwę pliku!");
Ważne szczegóły
Jeśli w katalogu docelowym istnieje już plik lub folder o podanej nazwie, metoda zgłosi wyjątek. Aby obejść to ograniczenie i zezwolić na zastąpienie, można użyć opcji StandardCopyOption.REPLACE_EXISTING.
Przykład:
Path source = Paths.get("old_name.txt");
Path target = Paths.get("new_name.txt");
// Zmieńmy nazwę pliku; jeśli już istnieje — zastąpimy go
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
W tym przykładzie plik "old_name.txt" zostanie przemianowany na "new_name.txt". Jeśli w folderze istniał już plik o takiej nazwie, zostanie on nadpisany.
Zmiana nazwy folderu
Path oldDir = Path.of("data/old_reports");
Path newDir = Path.of("data/archived_reports");
Files.move(oldDir, newDir);
System.out.println("Zmieniono nazwę folderu!");
4. Obsługa błędów przy kopiowaniu, przenoszeniu i zmianie nazw
Praca z systemem plików zawsze wiąże się z ryzykiem nieoczekiwanych sytuacji. Oto najczęstsze problemy:
Plik już istnieje.
Wyjątek: FileAlreadyExistsException. Rozwiązanie: użyj REPLACE_EXISTING, jeśli chcesz nadpisać.
Plik lub folder jest zajęty przez inny proces.
Wyjątek: IOException. Na przykład plik jest otwarty w innym programie.
Brak dostępu do pliku lub folderu.
Wyjątek: AccessDeniedException. Problem z uprawnieniami użytkownika.
Przenoszenie między różnymi systemami plików.
Wyjątek: AtomicMoveNotSupportedException. Nie wszystkie systemy plików obsługują przenoszenie atomowe.
Folder docelowy nie istnieje.
Przed kopiowaniem/przenoszeniem upewnij się, że folder docelowy został utworzony wcześniej!
Przykład obsługi błędów
try {
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
} catch (FileAlreadyExistsException e) {
System.out.println("Plik docelowy już istnieje: " + target);
} catch (AtomicMoveNotSupportedException e) {
System.out.println("Przenoszenie atomowe nie jest obsługiwane: " + e.getMessage());
} catch (IOException e) {
System.out.println("Błąd podczas przenoszenia: " + e.getMessage());
}
5. Praktyczne wskazówki
Sprawdzanie istnienia pliku/folderu docelowego
Przed kopiowaniem lub przenoszeniem zawsze warto sprawdzić, czy ścieżka docelowa nie jest zajęta:
if (Files.exists(target)) {
System.out.println("Plik już istnieje, nie będziemy nadpisywać.");
} else {
Files.copy(source, target);
}
Użycie plików tymczasowych dla bezpiecznych operacji
Przy złożonych operacjach (np. aktualizacja ważnych plików) często używa się plików tymczasowych — najpierw kopiuje się do pliku tymczasowego, a potem zastępuje plik główny:
Path temp = Path.of("data/report.tmp");
Files.copy(source, temp, StandardCopyOption.REPLACE_EXISTING);
Files.move(temp, target, StandardCopyOption.REPLACE_EXISTING);
Takie podejście minimalizuje ryzyko utraty danych przy awariach.
Przykład: wykonanie kopii zapasowej pliku przed zastąpieniem
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("Utworzono kopię zapasową.");
}
6. Tabela: najważniejsze metody i opcje
| Operacja | Metoda Java NIO | Uwagi |
|---|---|---|
| Kopiowanie | |
Nie kopiuje zawartości folderów! |
| Przenoszenie | |
Można użyć do zmiany nazwy |
| Zmiana nazwy | |
Nowa ścieżka w tym samym katalogu |
| Nadpisanie | |
Nadpisuje plik/folder docelowy |
| Sprawdzenie | |
Sprawdza istnienie pliku/folderu |
7. Typowe błędy przy kopiowaniu, przenoszeniu i zmianie nazw plików
Błąd nr 1: próba skopiowania pliku do nieistniejącego folderu. Jeśli katalog docelowy nie został utworzony, otrzymasz NoSuchFileException. Rozwiązanie: utworzyć folder wcześniej za pomocą Files.createDirectories.
Błąd nr 2: próba skopiowania całego folderu za pomocą Files.copy. Metoda skopiuje tylko „pustą skorupę”, a nie zawartość. Do pełnego kopiowania potrzebny jest rekursywny przebieg.
Błąd nr 3: brak obsługi istniejącego pliku. Jeśli nie przekażesz REPLACE_EXISTING, a plik już istnieje, zostanie zgłoszony wyjątek. Lepiej jawnie obsłużyć ten przypadek.
Błąd nr 4: próba zmiany nazwy, gdy plik o nowej nazwie już istnieje. Podobnie, otrzymasz FileAlreadyExistsException. Przed zmianą nazwy można sprawdzić istnienie pliku.
Błąd nr 5: przenoszenie między różnymi systemami plików. Czasem operacja nie jest wspierana „atomowo” i zgłaszany jest AtomicMoveNotSupportedException. W takim przypadku użyj zwykłego przeniesienia bez atomowości.
Błąd nr 6: brak uprawnień lub blokada pliku. Jeśli plik jest otwarty w innym programie lub brakuje praw do zapisu/odczytu, otrzymasz AccessDeniedException lub IOException. Zawsze obsługuj takie wyjątki.
GO TO FULL VERSION