CodeGym /Kursy /C# SELF /Przenoszenie plików i katalogów

Przenoszenie plików i katalogów

C# SELF
Poziom 40 , Lekcja 3
Dostępny

1. Wprowadzenie

Scenariuszy, kiedy potrzebne są operacje przenoszenia — mnóstwo: przenoszenie "pobranych" plików z tymczasowego folderu do folderu Dokumenty, masowe porządkowanie zdjęć, zmiana nazw według wzorca, przetwarzanie poczty i logów. System plików lubi porządek — albo przynajmniej jego namiastkę! A dobry programista powinien umieć ten porządek wprowadzić.

Do tego często pojawiają się takie zadania na rozmowach kwalifikacyjnych: "Napisz narzędzie, które zmieni nazwy wszystkich plików, dodając do nich numer wersji", albo "Zrób komendę, która przeniesie przestarzałe dokumenty do archiwum". Zobaczmy, jak to zrobić w C#.

Przegląd możliwości

W .NET są dwa główne sposoby na przenoszenie i zmienianie nazw — użyć metod statycznych (File.Move, Directory.Move) albo metod instancyjnych (FileInfo.MoveTo, DirectoryInfo.MoveTo). Wszystkie te metody pod maską robią prawie to samo — różni je głównie składnia.

Jak .NET "widzi" przenoszenie i zmianę nazwy?

Uwaga! Zmiana nazwy i przenoszenie — to w gruncie rzeczy ta sama operacja: plik lub folder w różnych miejscach systemu plików określany jest przez swoją ścieżkę. Jeśli ścieżka się zmienia — uznaje się, że obiekt "został przeniesiony" lub "zmieniono jego nazwę". Jeśli zmieniasz tylko nazwę, ale zostawiasz ten sam katalog — to zmiana nazwy. Jeśli zmieniasz całą ścieżkę — to przeniesienie. Filozofia jak u Schrödingera: obiekt jest i przeniesiony, i przemianowany, jeśli podasz nową ścieżkę z nową nazwą!

2. Przenoszenie i zmiana nazwy plików: przykłady

Będziemy iść od prostego do bardziej skomplikowanego i kontynuujemy na bazie naszego mini-menedżera plików.

Metoda statyczna File.Move

Oto przykład, jak przenieść (albo przemianować) plik:


// Przenosimy plik test1.txt do innego folderu z nową nazwą
File.Move(@"C:\Temp\test1.txt", @"C:\Archive\test1_archived.txt");

A jeśli chcesz po prostu zmienić nazwę pliku w tym samym folderze:


// Po prostu zmieniamy nazwę pliku
File.Move(@"C:\Temp\test1.txt", @"C:\Temp\test_renamed.txt");

I to cała magia! .NET po prostu "obcina" jedną ścieżkę i "przypisuje" obiektowi inną, jeśli obie ścieżki są dostępne i nie ma konfliktów.

Metoda statyczna Directory.Move

Z folderami — analogicznie:


// Przenosimy folder
Directory.Move(@"C:\Temp\OldFolder", @"C:\Temp\NewFolder");

Można zarówno zmieniać nazwę folderu (nowa nazwa w tym samym katalogu), jak i przenosić go w całości w inne miejsce.

3. Metody instancyjne: FileInfo.MoveTo i DirectoryInfo.MoveTo

Gdy masz już obiekt FileInfo albo DirectoryInfo, możesz wywołać metodę MoveTo():


var fileInfo = new FileInfo(@"C:\Temp\test1.txt");
fileInfo.MoveTo(@"C:\Archive\test1_archived.txt");

// Foldery:
var dirInfo = new DirectoryInfo(@"C:\Temp\OldFolder");
dirInfo.MoveTo(@"C:\Temp\NewFolder");

Tutaj też: jeśli nowa ścieżka to ten sam katalog, ale inna nazwa — następuje zmiana nazwy; jeśli inny katalog — przeniesienie.

4. A co jeśli plik już istnieje w miejscu docelowym?

Tu zaczynają się niuanse, które lubią "ukłuć" w najmniej odpowiednim momencie.

File.Move

Jeśli pod wskazaną ścieżką docelową jest już plik — zostanie wyrzucony wyjątek IOException, i twój kod "poleci":


try
{
    File.Move("data.txt", "archive\\data.txt");
}
catch (IOException ex)
{
    Console.WriteLine("Plik docelowy już istnieje! " + ex.Message);
}

FileInfo.MoveTo

Dokładnie ta sama sytuacja — IOException, jeśli plik docelowy już istnieje.

Directory.Move

W przypadku folderów jest jeszcze ostrzej: jeśli folder docelowy już istnieje — wyjątek. Nie da się przenieść folderu do folderu, który już jest zajęty.

Morał: Zawsze sprawdzaj, czy nie ma już takiego pliku lub folderu tam, gdzie próbujesz zapisać!


// Spokojnie sprawdzamy, czy plik istnieje pod docelową ścieżką
if (!File.Exists("archive\\data.txt"))
{
    File.Move("data.txt", "archive\\data.txt");
}
else
{
    Console.WriteLine("Plik docelowy już istnieje!");
}

5. Przydatne niuanse

Przykład zmiany nazwy folderu


var oldDir = @"C:\Projects\OldReport";
var newDir = @"C:\Projects\NewReport";

// Sprawdzamy, czy nie ma nowego folderu i czy istnieje stary
if (Directory.Exists(oldDir) && !Directory.Exists(newDir))
{
    Directory.Move(oldDir, newDir);
    Console.WriteLine("Folder został pomyślnie przemianowany.");
}
else
{
    Console.WriteLine("Błąd: folder źródłowy nie znaleziony lub nowy już istnieje.");
}

Zmiana nazwy z uwzględnieniem zawartości zagnieżdżonej

Cała zawartość folderu (podfoldery, pliki) zostanie przeniesiona razem z nim bez dodatkowych poleceń! To wygodne: jedną komendą folder z dowolną zagnieżdżonością trafia w nowe miejsce.

Najlepsze praktyki i przydatne metody klasy Path

Kiedy zmieniasz nazwy lub przenosisz pliki, używaj metod z klasy System.IO.Path, żeby poprawnie zbudować nową ścieżkę lub zmodyfikować nazwę pliku:

  • Pobrać nazwę pliku bez rozszerzenia: Path.GetFileNameWithoutExtension(path)
  • Zamienić tylko rozszerzenie: Path.ChangeExtension(path, ".bak")
  • Zbudować nową ścieżkę z inną nazwą: Path.Combine(Path.GetDirectoryName(path), "newname.txt")

string oldPath = @"C:\Reports\2023_Final.docx";
string newName = "2023_Archive.docx";
string newPath = Path.Combine(Path.GetDirectoryName(oldPath)!, newName);

File.Move(oldPath, newPath);

6. Ważne niuanse i typowe błędy

Uprawnienia i blokady

Jeśli nie masz uprawnień do zapisu w jednej ze ścieżek — zostanie rzucony wyjątek UnauthorizedAccessException. Podobnie, jeśli plik jest używany przez inny proces (np. otwarty w Word), dostaniesz błąd. To bardzo częsty przypadek.

Przenoszenie między różnymi dyskami i woluminami

W praktyce File.Move realizuje szybką operację zmiany nazwy w obrębie jednego woluminu/dysku. Jeśli spróbujesz przenieść plik z dysku C na dysk D — .NET automatycznie wykona kopiowanie z późniejszym usunięciem pliku źródłowego. Jeśli coś pójdzie nie tak (np. dysk docelowy jest pełny), plik źródłowy pozostanie na miejscu.

Ciekawostka: niemal wszystkie nowoczesne systemy plików wspierają "szybką zmianę nazwy/przeniesienie" wewnątrz woluminu, a przy przenoszeniu między woluminami — kopiowanie + usunięcie.

Przenoszenie całych folderów (Directory.Move)

Nie można przenieść folderu do środka samego siebie ani do folderu w nim zagnieżdżonego (np. C:\Data do C:\Data\Archive) — to spowoduje błąd.

Jak bezpiecznie przenosić?

Przed każdym przeniesieniem, szczególnie masowym, sprawdzaj istnienie źródła (File.Exists, Directory.Exists) i brak konfliktu w miejscu docelowym. I nie zapominaj o try-catch: system plików to kapryśna dama, może rzucić błąd w najmniej oczekiwanym momencie.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION