Zapis plików w C# – File i StreamWriter
Nauczysz się zapisywać dane do plików: nadpisywanie, dopisywanie, zapis linia po linii oraz praktyczne wzorce pracy z plikami.
Nadpisywanie vs dopisywanie
Przy zapisie do pliku masz dwie opcje: nadpisać (usunąć starą zawartość) lub dopisać (dodać na końcu).
| Metoda | Działanie | Plik nie istnieje? |
|---|---|---|
WriteAllText() | Nadpisuje (usuwa starą zawartość) | Tworzy nowy |
WriteAllLines() | Nadpisuje (tablica → linie) | Tworzy nowy |
AppendAllText() | Dopisuje na końcu | Tworzy nowy |
AppendAllLines() | Dopisuje linie na końcu | Tworzy nowy |
WriteAllText() bezpowrotnie usuwa poprzednią zawartość pliku! Jeśli chcesz dodać tekst do istniejącego pliku, użyj AppendAllText().
File.WriteAllText() – zapis całego tekstu
Najprostsza metoda – zapisuje cały string do pliku (nadpisuje jeśli istnieje).
using System.IO; // Zapis tekstu do pliku (tworzy nowy lub nadpisuje istniejący) string tekst = "To jest przykładowy tekst.\nDruga linia."; File.WriteAllText("nowyPlik.txt", tekst); Console.WriteLine("Plik został zapisany!"); // Możemy też użyć interpolacji string imie = "Anna"; int wiek = 20; File.WriteAllText("dane.txt", $"Imię: {imie}\nWiek: {wiek}");
Użyj \n dla nowej linii lub Environment.NewLine dla systemowego znaku nowej linii (Windows: \r\n, Linux: \n).
Wieloliniowy tekst z @”…”
// Verbatim string – zachowuje formatowanie string raport = @"=== RAPORT === Data: 2025-01-15 Autor: Jan Kowalski Zawartość raportu..."; File.WriteAllText("raport.txt", raport);
File.WriteAllLines() – zapis tablicy jako linie
Zapisuje tablicę stringów – każdy element staje się osobną linią w pliku.
using System.IO; // Tablica stringów → każdy element = nowa linia string[] linie = { "Pierwsza linia", "Druga linia", "Trzecia linia" }; File.WriteAllLines("linie.txt", linie); // Wynik w pliku: // Pierwsza linia // Druga linia // Trzecia linia
[1] „ma”
[2] „kota”
ma
kota
Praktyczny przykład – lista zakupów
using System.IO; using System.Collections.Generic; List<string> zakupy = new List<string>(); zakupy.Add("Chleb"); zakupy.Add("Mleko"); zakupy.Add("Masło"); // List<string> też działa z WriteAllLines! File.WriteAllLines("zakupy.txt", zakupy);
File.AppendAllText() – dopisywanie
Dopisuje tekst na końcu pliku (nie usuwa poprzedniej zawartości).
using System.IO; // Dopisanie tekstu na końcu pliku File.AppendAllText("log.txt", "Nowy wpis w logu\n"); // Dopisanie z datą i godziną string wpis = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] Program uruchomiony\n"; File.AppendAllText("log.txt", wpis); // Dopisanie tablicy linii string[] noweWpisy = { "Wpis 1", "Wpis 2" }; File.AppendAllLines("log.txt", noweWpisy);
AppendAllText() NIE dodaje automatycznie nowej linii. Jeśli chcesz każdy wpis w nowej linii, sam dodaj \n na końcu tekstu.
Praktyczny przykład – prosty logger
using System.IO; static void Loguj(string wiadomosc) { string wpis = $"[{DateTime.Now:HH:mm:ss}] {wiadomosc}"; File.AppendAllText("app.log", wpis + Environment.NewLine); } // Użycie Loguj("Program uruchomiony"); Loguj("Użytkownik zalogowany: Jan"); Loguj("Błąd: nieprawidłowe hasło");
StreamWriter – zapis linia po linii
StreamWriter pozwala zapisywać do pliku stopniowo – linia po linii. Idealny gdy generujesz dane w pętli.
using System.IO; // using automatycznie zamyka plik po zakończeniu bloku! using (StreamWriter writer = new StreamWriter("plik.txt")) { writer.WriteLine("Pierwsza linia"); writer.WriteLine("Druga linia"); writer.Write("Tekst bez nowej linii"); writer.Write(" - kontynuacja"); } // Tutaj plik jest automatycznie zamknięty i zapisany
| Metoda | Opis |
|---|---|
WriteLine(tekst) | Zapisuje tekst z nową linią na końcu |
Write(tekst) | Zapisuje tekst bez nowej linii |
Flush() | Wymusza zapis bufora na dysk |
StreamWriter z dopisywaniem (append)
using System.IO; // Domyślnie nadpisuje plik using (StreamWriter writer = new StreamWriter("plik.txt")) { writer.WriteLine("Nowa zawartość"); } // Z parametrem append: true – dopisuje na końcu using (StreamWriter writer = new StreamWriter("plik.txt", append: true)) { writer.WriteLine("Ta linia zostanie dopisana"); }
Praktyczny przykład – generowanie tabliczki mnożenia
using System.IO; using (StreamWriter writer = new StreamWriter("tabliczka.txt")) { writer.WriteLine("=== TABLICZKA MNOŻENIA ==="); writer.WriteLine(); for (int i = 1; i <= 10; i++) { for (int j = 1; j <= 10; j++) { writer.Write($"{i * j,4}"); // ,4 = szerokość 4 znaki } writer.WriteLine(); // Nowa linia po każdym wierszu } } Console.WriteLine("Tabliczka zapisana do pliku!");
using gwarantuje, że plik zostanie zamknięty i zapisany nawet jeśli wystąpi błąd. Bez using dane mogą nie zostać zapisane na dysk!
Obsługa błędów przy zapisie
using System.IO; try { File.WriteAllText("dane.txt", "Zawartość pliku"); Console.WriteLine("✅ Plik zapisany pomyślnie!"); } catch (UnauthorizedAccessException) { Console.WriteLine("❌ Brak uprawnień do zapisu!"); } catch (DirectoryNotFoundException) { Console.WriteLine("❌ Folder nie istnieje!"); } catch (IOException ex) { Console.WriteLine($"❌ Błąd zapisu: {ex.Message}"); }
Najczęstsze wyjątki przy zapisie
| Wyjątek | Kiedy występuje? |
|---|---|
UnauthorizedAccessException | Brak uprawnień do zapisu (plik tylko do odczytu) |
DirectoryNotFoundException | Folder docelowy nie istnieje |
IOException | Plik jest otwarty przez inny program, brak miejsca na dysku |
PathTooLongException | Ścieżka za długa (max ~260 znaków w Windows) |
Kodowanie znaków (polskie znaki)
using System.IO; using System.Text; string tekst = "Zażółć gęślą jaźń - polskie znaki ąćęłńóśźż"; // Zapis z kodowaniem UTF-8 (zalecane!) File.WriteAllText("polski.txt", tekst, Encoding.UTF8); // StreamWriter z kodowaniem using (StreamWriter writer = new StreamWriter("polski2.txt", false, Encoding.UTF8)) { writer.WriteLine(tekst); }
Encoding.UTF8 to uniwersalne kodowanie – obsługuje polskie znaki, emoji i wszystkie języki świata. Zawsze określaj kodowanie jawnie.
Praktyczne wzorce pracy z plikami
Wzorzec: Tworzenie pliku jeśli nie istnieje
string sciezka = "konfiguracja.txt"; if (!File.Exists(sciezka)) { // Plik nie istnieje – tworzymy z domyślną zawartością string domyslna = "jezyk=pl\ntemat=jasny\nczcionka=14"; File.WriteAllText(sciezka, domyslna); Console.WriteLine("Utworzono plik konfiguracyjny."); } else { Console.WriteLine("Plik konfiguracyjny już istnieje."); }
Wzorzec: Backup przed nadpisaniem
string sciezka = "dane.txt"; string noweDane = "Nowe dane do zapisania"; // Jeśli plik istnieje, zrób backup if (File.Exists(sciezka)) { string backup = $"dane_backup_{DateTime.Now:yyyyMMdd_HHmmss}.txt"; File.Copy(sciezka, backup); Console.WriteLine($"Backup utworzony: {backup}"); } // Teraz bezpiecznie nadpisujemy File.WriteAllText(sciezka, noweDane);
Wzorzec: Prosty program do notatek
using System.IO; string plik = "notatki.txt"; while (true) { Console.Write("Wpisz notatkę (lub 'koniec'): "); string notatka = Console.ReadLine(); if (notatka.ToLower() == "koniec") break; if (!string.IsNullOrWhiteSpace(notatka)) { string wpis = $"[{DateTime.Now:dd.MM.yyyy HH:mm}] {notatka}"; File.AppendAllText(plik, wpis + Environment.NewLine); Console.WriteLine("✅ Notatka zapisana!"); } } Console.WriteLine("Program zakończony.");
Częste błędy
❌ Błąd 1: Zapomnienie o nowej linii przy Append
❌ Źle
AppendAllText("log.txt", "Wpis1");
AppendAllText("log.txt", "Wpis2");
Wynik: „Wpis1Wpis2” (wszystko w jednej linii)
✅ Dobrze
AppendAllText("log.txt", "Wpis1\n");
AppendAllText("log.txt", "Wpis2\n");
Każdy wpis w osobnej linii
❌ Błąd 2: Brak using dla StreamWriter
❌ Źle
StreamWriter w = new StreamWriter(...);
w.WriteLine("tekst");
Plik może nie zostać zapisany!
✅ Dobrze
using (StreamWriter w = ...)
{ w.WriteLine("tekst"); }
Automatyczne zamknięcie i zapis
❌ Błąd 3: WriteAllText zamiast AppendAllText
❌ Niebezpieczne
WriteAllText("log.txt", nowyWpis);
Usuwa wszystkie poprzednie wpisy!
✅ Bezpieczne
AppendAllText("log.txt", nowyWpis);
Dopisuje na końcu
Podsumowanie
Metody zapisu plików
| Metoda | Działanie | Kiedy używać? |
|---|---|---|
File.WriteAllText() | Nadpisuje plik tekstem | Zapis całego tekstu naraz |
File.WriteAllLines() | Nadpisuje tablicą linii | Zapis listy/tablicy |
File.AppendAllText() | Dopisuje tekst | Logi, notatki, historia |
File.AppendAllLines() | Dopisuje tablicę linii | Dodawanie wielu wpisów |
StreamWriter | Zapis linia po linii | Generowanie danych w pętli |
1. Używaj try-catch dla obsługi błędów
2. Określ kodowanie Encoding.UTF8 dla polskich znaków
3. Używaj using dla StreamWriter
4. Rozróżniaj WriteAllText (nadpisuje) od AppendAllText (dopisuje)
5. Pamiętaj o \n przy AppendAllText!
Zadania praktyczne
📝 Zadanie 1: Prosty zapis
Napisz program, który:
- Pobiera od użytkownika imię i wiek
- Zapisuje do pliku „osoba.txt” w formacie „Imię: X, Wiek: Y”
- Wyświetla potwierdzenie zapisu
📝 Zadanie 2: Lista zakupów
Napisz program, który:
- Pozwala użytkownikowi dodawać produkty do listy
- Po wpisaniu „koniec” zapisuje listę do pliku „zakupy.txt”
- Każdy produkt w osobnej linii
💡 Podpowiedź: Użyj List<string> i WriteAllLines()
📝 Zadanie 3: Dziennik
Napisz program „dziennik”, który:
- Pozwala pisać wpisy (każdy z datą i godziną)
- Dopisuje wpisy do pliku „dziennik.txt” (nie nadpisuje!)
- Po wpisaniu „czytaj” wyświetla całą zawartość dziennika
⭐ Zadanie 4: Generator tabeli
Napisz program, który:
- Pobiera od użytkownika liczbę N
- Generuje tabliczkę mnożenia N×N
- Zapisuje do pliku „tabliczka.txt” w ładnym formacie
💡 Podpowiedź: Użyj StreamWriter i formatowania {wynik,4}
⭐⭐ Zadanie 5: Konwerter CSV
Napisz program, który:
- Pobiera dane osób (imię, nazwisko, email) w pętli
- Zapisuje do pliku CSV „osoby.csv”
- Pierwsza linia to nagłówki: „Imie,Nazwisko,Email”
- Dodaje opcję dopisywania nowych osób do istniejącego pliku