Odczyt plików w C# – File i StreamReader
Nauczysz się wczytywać dane z plików tekstowych: cały plik naraz, linia po linii oraz obsługiwać błędy i kodowanie.
Przestrzeń nazw System.IO
Wszystkie operacje na plikach w C# znajdują się w przestrzeni nazw System.IO. Musimy ją dołączyć na początku programu.
using System.IO; class Program { static void Main() { // Teraz możemy używać klas File, StreamReader, Path... } }
Najważniejsze klasy do odczytu plików
| Klasa | Do czego służy? |
|---|---|
File | Statyczna klasa do prostych operacji (cały plik naraz) |
StreamReader | Odczyt linia po linii (dla dużych plików) |
Path | Operacje na ścieżkach plików |
Directory | Operacje na folderach |
Mały plik (do kilku MB) → File.ReadAllText() lub ReadAllLines()
Duży plik (dziesiątki MB+) → StreamReader (czyta linia po linii, oszczędza pamięć)
Sprawdzanie czy plik istnieje
Przed odczytem zawsze sprawdź czy plik istnieje – unikniesz błędów!
using System.IO; string nazwaPliku = "dane.txt"; if (File.Exists(nazwaPliku)) { Console.WriteLine("Plik istnieje - mogę go odczytać!"); string zawartosc = File.ReadAllText(nazwaPliku); Console.WriteLine(zawartosc); } else { Console.WriteLine("Plik nie istnieje!"); }
File.Exists(ścieżka) zwraca true jeśli plik istnieje, false jeśli nie istnieje. Nie rzuca wyjątku!
File.ReadAllText() – cały plik jako string
Najprostsza metoda – wczytuje cały plik do jednej zmiennej string.
using System.IO; // Wczytanie całego pliku do jednego stringa string zawartosc = File.ReadAllText("plik.txt"); Console.WriteLine("Zawartość pliku:"); Console.WriteLine(zawartosc); // Możemy użyć metod stringowych Console.WriteLine($"Liczba znaków: {zawartosc.Length}"); Console.WriteLine($"Zawiera 'C#': {zawartosc.Contains("C#")}");
Dla bardzo dużych plików (setki MB) – cały plik trafia do pamięci RAM! Użyj wtedy StreamReader.
File.ReadAllLines() – tablica linii
Wczytuje plik i zwraca tablicę stringów – każda linia to osobny element.
using System.IO; // Wczytanie pliku jako tablicy linii string[] linie = File.ReadAllLines("plik.txt"); Console.WriteLine($"Plik ma {linie.Length} linii"); // Iteracja przez wszystkie linie foreach (string linia in linie) { Console.WriteLine(linia); } // Dostęp do konkretnej linii (indeks od 0!) Console.WriteLine($"Pierwsza linia: {linie[0]}"); Console.WriteLine($"Ostatnia linia: {linie[linie.Length - 1]}");
Linia 2
Linia 3
[1] „Linia 2”
[2] „Linia 3”
Kiedy używać ReadAllLines?
| Użyj ReadAllLines gdy… | Użyj ReadAllText gdy… |
|---|---|
| Przetwarzasz plik linia po linii | Potrzebujesz całego tekstu jako jeden string |
| Czytasz pliki CSV, logi, listy | Wyszukujesz tekst w całym pliku |
| Chcesz dostęp do konkretnej linii | Wyświetlasz całą zawartość |
StreamReader – odczyt linia po linii
StreamReader czyta plik linia po linii – idealny dla dużych plików, bo nie ładuje całości do pamięci.
using System.IO; // using automatycznie zamyka plik po zakończeniu bloku! using (StreamReader reader = new StreamReader("plik.txt")) { string linia; // ReadLine() zwraca null gdy koniec pliku while ((linia = reader.ReadLine()) != null) { Console.WriteLine(linia); } } // Tutaj plik jest już automatycznie zamknięty
Instrukcja using automatycznie zamyka plik po zakończeniu bloku kodu (nawet jeśli wystąpi błąd!). Bez using musielibyśmy ręcznie wywołać reader.Close().
ReadToEnd() – reszta pliku jako string
using (StreamReader reader = new StreamReader("plik.txt")) { // Czytamy pierwszą linię osobno string naglowek = reader.ReadLine(); Console.WriteLine($"Nagłówek: {naglowek}"); // Reszta pliku jako jeden string string reszta = reader.ReadToEnd(); Console.WriteLine($"Pozostała treść:\n{reszta}"); }
| Metoda | Zwraca | Opis |
|---|---|---|
ReadLine() | string lub null | Jedna linia (null = koniec pliku) |
ReadToEnd() | string | Cała reszta pliku |
EndOfStream | bool | Czy osiągnięto koniec pliku? |
Obsługa błędów (try-catch)
Operacje na plikach mogą generować wyjątki. Zawsze je obsługuj!
using System.IO; try { string zawartosc = File.ReadAllText("plik.txt"); Console.WriteLine(zawartosc); } catch (FileNotFoundException) { Console.WriteLine("❌ Plik nie został znaleziony!"); } catch (UnauthorizedAccessException) { Console.WriteLine("❌ Brak uprawnień do odczytu pliku!"); } catch (IOException ex) { Console.WriteLine($"❌ Błąd odczytu: {ex.Message}"); }
Najczęstsze wyjątki przy odczycie
| Wyjątek | Kiedy występuje? |
|---|---|
FileNotFoundException | Plik nie istnieje |
DirectoryNotFoundException | Folder nie istnieje |
UnauthorizedAccessException | Brak uprawnień do odczytu |
IOException | Ogólny błąd I/O (plik zajęty itp.) |
Najlepiej użyć obu! File.Exists() dla typowych przypadków, try-catch dla nieoczekiwanych błędów (np. plik usunięty między sprawdzeniem a odczytem).
Kodowanie znaków (polskie znaki)
Jeśli plik zawiera polskie znaki (ą, ę, ć…), musisz określić kodowanie.
using System.IO; using System.Text; // Odczyt z kodowaniem UTF-8 (obsługuje polskie znaki) string tekst = File.ReadAllText("plik.txt", Encoding.UTF8); // StreamReader z kodowaniem using (StreamReader reader = new StreamReader("plik.txt", Encoding.UTF8)) { string linia = reader.ReadLine(); }
| Kodowanie | Opis | Kiedy używać? |
|---|---|---|
Encoding.UTF8 | Uniwersalne (polskie, emoji, wszystkie języki) | Domyślny wybór! |
Encoding.Default | Systemowe (zależy od Windows) | Stare pliki Windows |
Encoding.ASCII | Tylko angielskie znaki | Pliki bez polskich znaków |
Jeśli widzisz Ĺ› zamiast ś, plik ma inne kodowanie niż UTF-8. Spróbuj Encoding.Default lub Encoding.GetEncoding(1250) (Windows-1250).
Ścieżki do plików
Ścieżka względna vs bezwzględna
using System.IO; // Ścieżka WZGLĘDNA (od folderu z programem) string wzgledna = "dane.txt"; // W tym samym folderze string wzgledna2 = "dane/plik.txt"; // W podfolderze "dane" // Ścieżka BEZWZGLĘDNA (pełna ścieżka) string bezwzgledna = @"C:\Users\Jan\Dokumenty\dane.txt"; // Bieżący katalog programu string obecnyFolder = Directory.GetCurrentDirectory(); Console.WriteLine($"Program uruchomiony z: {obecnyFolder}");
Symbol @ przed stringiem tworzy verbatim string – nie interpretuje znaków specjalnych. Bez tego musielibyśmy pisać "C:\\Users\\Jan" (podwójny backslash).
Path.Combine() – bezpieczne łączenie ścieżek
using System.IO; // ❌ Źle – ręczne łączenie string zle = "C:\\dane" + "\\" + "plik.txt"; // ✅ Dobrze – Path.Combine string dobrze = Path.Combine("C:\\dane", "plik.txt"); // Można łączyć wiele części string sciezka = Path.Combine("dane", "pliki", "dokument.txt"); // Wynik: "dane\pliki\dokument.txt" (Windows) lub "dane/pliki/dokument.txt" (Linux)
Automatycznie dodaje \ lub / w zależności od systemu operacyjnego. Działa poprawnie nawet gdy jedna część kończy się ukośnikiem, a druga zaczyna.
Częste błędy
❌ Błąd 1: Brak sprawdzenia czy plik istnieje
❌ Źle
string t = File.ReadAllText("plik.txt");
Rzuci wyjątek jeśli plik nie istnieje!
✅ Dobrze
if (File.Exists("plik.txt"))
Najpierw sprawdź!
❌ Błąd 2: Nieprawidłowe backslashe w ścieżce
❌ Źle
"C:\dane\plik.txt"
\d i \p to znaki specjalne!
✅ Dobrze
@"C:\dane\plik.txt"
lub "C:\\dane\\plik.txt"
❌ Błąd 3: Zapomnienie o using dla StreamReader
❌ Źle
StreamReader r = new StreamReader(...);
// ... użycie ...
Plik pozostaje otwarty!
✅ Dobrze
using (StreamReader r = ...)
{ ... }
Plik automatycznie zamknięty!
Podsumowanie
Metody odczytu plików
| Metoda | Zwraca | Kiedy używać? |
|---|---|---|
File.ReadAllText() | string | Mały plik, potrzebujesz całego tekstu |
File.ReadAllLines() | string[] | Przetwarzanie linia po linii |
StreamReader.ReadLine() | string | Duże pliki, oszczędność pamięci |
Metody pomocnicze
| Metoda | Opis |
|---|---|
File.Exists(ścieżka) | Sprawdza czy plik istnieje |
Path.Combine(a, b) | Łączy części ścieżki |
Directory.GetCurrentDirectory() | Bieżący folder programu |
1. Sprawdź czy plik istnieje (File.Exists)
2. Użyj try-catch dla obsługi błędów
3. Określ kodowanie dla polskich znaków (Encoding.UTF8)
4. Używaj using dla StreamReader
Zadania praktyczne
📝 Zadanie 1: Podstawowy odczyt
Napisz program, który:
- Sprawdza czy plik „dane.txt” istnieje
- Jeśli tak – wyświetla jego zawartość
- Jeśli nie – wyświetla komunikat „Plik nie istnieje”
📝 Zadanie 2: Licznik linii
Napisz program, który:
- Wczytuje plik tekstowy
- Liczy i wyświetla liczbę linii
- Wyświetla pierwszą i ostatnią linię
💡 Podpowiedź: Użyj File.ReadAllLines()
📝 Zadanie 3: Wyszukiwarka w pliku
Napisz program, który:
- Pobiera od użytkownika szukaną frazę
- Wczytuje plik i sprawdza które linie zawierają tę frazę
- Wyświetla numery linii i ich treść
💡 Podpowiedź: linia.Contains(fraza)
⭐ Zadanie 4: Statystyki pliku
Napisz program, który dla podanego pliku wyświetla:
- Liczbę linii
- Liczbę słów (podziel po spacjach)
- Liczbę znaków (bez spacji)
- Najdłuższą linię
⭐⭐ Zadanie 5: Czytnik CSV
Napisz program, który:
- Wczytuje plik CSV (np. „osoby.csv”)
- Pierwszą linię traktuje jako nagłówki
- Wyświetla dane w formie: „Nagłówek: wartość”
- Obsługuje błędy (plik nie istnieje, pusty plik)