Pliki tekstowe — program, który pamięta po zamknięciu

Lista wyników znika po zakończeniu programu. Zapiszemy ją w pliku, a potem odczytamy. Przy okazji ustalimy, gdzie plik naprawdę powstaje.

C#Technikum
CEL LEKCJI

Czego się dziś nauczysz

  • Zapiszesz i odczytasz plik tekstowy.
  • Odróżnisz ścieżkę względną od bezwzględnej.
  • Wyjaśnisz nadpisywanie oraz kodowanie UTF-8.

Przygotowanie: lekcje 01–35. Przewidywany czas: 45–90 minut z zadaniami. Przykłady wymagają .NET 8 lub nowszego, z włączonymi ImplicitUsings i Nullable.

TEORIA

Wyjaśnienie krok po kroku

Gdzie jest plik

Ścieżka "wyniki.txt" jest względna wobec bieżącego katalogu roboczego procesu. Directory.GetCurrentDirectory() zwraca jego pełną ścieżkę. Path.Combine łączy części ścieżki z odpowiednim separatorem. Nie zakładaj, że plik powstanie obok Program.cs.

Zapis nadpisuje

File.WriteAllLines zapisuje tablicę wierszy. Jeśli plik już istnieje, jego dotychczasowa zawartość jest zastępowana. File.AppendAllText dopisuje tekst na końcu. Przykład używa nazwy cwiczenie-wyniki.txt i jest przeznaczony do osobnego folderu ćwiczeń.

Kodowanie i błędy

Kodowanie określa sposób zapisu znaków jako bajtów. Jawne Encoding.UTF8 przy zapisie i odczycie upraszcza pracę z polskimi literami. Brak uprawnień i problemy dysku wymagają obsługi, nawet jeśli nazwa pliku wygląda poprawnie. Metody WriteAllLines i ReadAllLines same zamykają używane zasoby.

PRZYKŁAD

Przykład do zbadania

Wklej cały przykład do nowego projektu konsolowego jako Program.cs. Zastąp poprzednią zawartość pliku. Nie łącz kilku całych programów w jednym pliku.

Program.cs — cały plik
using System;
using System.IO;
using System.Text;

string sciezka = Path.Combine(Directory.GetCurrentDirectory(), "cwiczenie-wyniki.txt");
string[] wyniki = { "Ala;8", "Ola;10" };
try
{
    File.WriteAllLines(sciezka, wyniki, Encoding.UTF8);
    string[] wiersze = File.ReadAllLines(sciezka, Encoding.UTF8);
    foreach (string wiersz in wiersze) Console.WriteLine(wiersz);
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Brak uprawnien do pliku.");
}
catch (IOException)
{
    Console.WriteLine("Nie udalo sie zapisac lub odczytac pliku.");
}
Oczekiwany wynik
Ala;8
Ola;10

Co dzieje się po kolei

  • Wynik poniżej zakłada udany zapis i odczyt w folderze ćwiczeń.
  • Plik zawiera dwa wiersze, a ReadAllLines zwraca je jako string[].
  • Średnik jest umownym separatorem danych w tym prostym formacie; nie tworzymy pełnego formatu CSV.

Pobierz Program.cs

ELEMENTY WBUDOWANE

Użyte w tej lekcji elementy

Metody .NET są gotowymi narzędziami biblioteki. Instrukcje języka i nasze metody oznaczamy osobno. Właściwości, np. Length, odczytujemy bez nawiasów.

Element Wynik Działanie i ograniczenia
Directory.GetCurrentDirectory() string Pełna ścieżka katalogu roboczego.
Path.Combine(a, b) string Łączy części ścieżki; nie tworzy pliku ani folderu.
File.WriteAllLines(sciezka, wiersze, kodowanie) void Tworzy lub nadpisuje plik wierszami.
File.ReadAllLines(sciezka, kodowanie) string[] Wczytuje cały plik do pamięci i zwraca wiersze.
File.AppendAllText(sciezka, tekst) void Dopisuje tekst; sam nie dodaje znaku końca wiersza.
Encoding.UTF8 Encoding Właściwość udostępniająca kodowanie UTF-8.
Console.WriteLine(wartosc) void Wypisuje wartość w konsoli.
CZĘSTE BŁĘDY

Częste błędy

  • WriteAllLines nie dopisuje do istniejących danych.
  • Sprawdzenie File.Exists nie gwarantuje, że późniejszy odczyt się uda.
  • ReadAllLines nie jest dobrym wyborem dla plików, które nie mieszczą się w pamięci.
TEORIA

using, IDisposable i strumienie

File.ReadAllLines i File.WriteAllLines otwierają i zamykają plik same. Gdy plik jest duży albo chcesz czytać wiersz po wierszu, sięgasz po strumień — a strumień trzeba zamknąć.

Program.cs — fragment
using (StreamReader czytnik = new StreamReader("dane.txt"))
{
    string? wiersz;
    while ((wiersz = czytnik.ReadLine()) != null)
    {
        Console.WriteLine(wiersz);
    }
}   // tutaj plik zostaje zamkniety — nawet gdy w srodku wystapil wyjatek

Instrukcja using obiecuje jedno: przy wyjściu z bloku wywoła metodę Dispose obiektu. Mogą z niej korzystać wszystkie typy implementujące interfejs IDisposable — strumienie plików, połączenia z bazą danych, obrazy. Zapis skrócony bez klamer, using StreamReader czytnik = new StreamReader("dane.txt");, zamyka obiekt na końcu metody.

Bez using

Niezamknięty strumień trzyma plik zajęty: kolejna próba zapisu może zakończyć się IOException, a część danych zostać w buforze i nie trafić na dysk. Odśmiecacz kiedyś to posprząta, ale nie wiadomo kiedy — dlatego zamknięcie zasobu jest zadaniem programisty, a nie środowiska.

Kiedy plik zniknie

Brak pliku, brak uprawnień i zapełniony dysk to typowe sytuacje na wyjątek. Obsługę takich błędów poznałeś w lekcji 35 — zastosuj ją do każdej operacji na pliku.

ZADANIA

Zadania

ZAD 1Znajdź plik★☆☆

Wypisz sciezka i znajdź plik w menedżerze plików.

Sprawdź: Plik zawiera dokładnie Ala;8 i Ola;10 w osobnych wierszach.

ZAD 2Trzeci wynik★★☆

Dodaj trzeci wiersz do tablicy wyniki i uruchom zapis ponownie.

Sprawdź: Plik ma trzy, a nie pięć wierszy.

ZAD 3Suma z tekstu★★★

Dla tablicy wierszy { "8", "kot", "10" } zsumuj poprawne liczby i policz błędne wiersze.

Sprawdź: Suma 18; błędne wiersze 1.

ZAD +Czytnik z prawdziwym plikiem★★★

Napisz program, który wczytuje plik dane.txt z wierszami w formacie imie;punkty i buduje z nich zestawienie.

Wymagania: brak pliku i brak uprawnień mają dawać dwa różne komunikaty; wiersz o złej liczbie pól oraz punkty niebędące liczbą mają być pominięte z komunikatem, ale nie mogą przerwać programu. Odczyt zamknij tak, żeby plik został zwolniony także wtedy, gdy w środku wystąpi błąd. Na koniec zapisz do pliku raport.txt liczbę wierszy poprawnych i odrzuconych oraz sumę punktów.

Przygotuj sobie plik testowy z co najmniej jednym wierszem poprawnym i dwoma uszkodzonymi, a potem uruchom program jeszcze raz po zmianie nazwy pliku wejściowego, żeby sprawdzić obsługę braku pliku.

PODSUMOWANIE

Sprawdź, czy rozumiesz

Wyjaśnij własnymi słowami, jak działa główny przykład i dlaczego daje taki wynik. Następnie zmień jedną daną i przewidź wynik przed uruchomieniem. Wróć do celów lekcji i sprawdź, które potrafisz już wykonać samodzielnie.

Dokumentacja: Microsoft Learn — temat tej lekcji.