W poprzednim tygodniu poznaliśmy
podstawowe operacje wejściowe oraz wyjściowe, jakie oferuje nam język obiektowy
C# 2.0. Nauczyliśmy się już zapisywać dane do pliku oraz je czytać. Dzisiaj
poszerzymy sobie jeszcze naszą wiedzę na w/w temat, ale de facto dzisiejszy
artykuł będzie poświęcony głównie metodom i właściwościom umożliwiającym
manipulację plików oraz katalogów.
Zanim przejdziemy do meritum
przypomnijmy sobie poznane przez nas tydzień temu operacje. W tym celu napiszmy
prosty programik:
using System;
using System.IO;
namespace CentrumXP_19
{
class MojaKlasa
{
FileStream
fsZapis, fsOdczyt;
void Zapis()
{
fsZapis = new FileStream("C://mojPlik.txt", FileMode.Create);
StreamWriter sw = new
StreamWriter(fsZapis);
Console.WriteLine("Podaj Twoj ulubiony kolor:");
sw.WriteLine(Console.ReadLine());
sw.Close();
Console.WriteLine("Dane zostały zapisane do pliku tekstowego!");
}
void Odczyt()
{
string odczyt;
fsOdczyt = new FileStream("C://mojPlik.txt", FileMode.Open);
StreamReader sr = new
StreamReader(fsOdczyt);
Console.WriteLine("Odczytujemy dane z pliku.");
while ((odczyt=
sr.ReadLine()) != null)
{
Console.WriteLine("Twój ulubiony kolor to: {0}.", odczyt);
}
Console.WriteLine("Koniec odczytu z pliku tekstowego.");
}
static void Main()
{
MojaKlasa
mk = new MojaKlasa();
mk.Zapis();
Console.WriteLine();
mk.Odczyt();
}
}
}
Powyższy przykład jest
przypomnieniem wiedzy, jaką zdobyliśmy w poprzednim tygodniu. Zdefiniowaliśmy
sobie bowiem dwie metody, które odpowiednio zapisują do pliku tekstowego dane
wprowadzone przez użytkownika (plik ten jest tworzony na dysku C pod nazwą: mojPlik.txt)
oraz odczytują je z tegoż pliku. Obie te metody są wywołane w odpowiedni sposób
w głównej metodzie statycznej Main().
Po skompilowaniu i uruchomieniu
powyższego przykładu otrzymamy na ekranie następujące wyniki:

Znamy już przeznaczenie potężnej
klasy FileStream, a także obiektów typu StreamWriter oraz StreamReader.
Potrafimy już tworzyć pliki tekstowe (modyfikować je) i odczytywać z nich
wpisane wcześniej informacje. Do tej pory jednak przedstawiliśmy bardzo prosty
sposób tworzenia plików. Teraz chcemy poszerzyć tę wiedzę, która będzie stricte
powiązana z manipulacją właśnie plików oraz katalogów, o których jak na razie
nic nie pisaliśmy.
Potrzebne klasy do manipulacji
plików i katalogów znajdują się w przestrzeni nazw System.IO. Są to między
innymi: klasa File, która reprezentuje plik na dysku oraz klasa Directory,
która odpowiada za różnego rodzaju działania na katalogach.
Klasa Directory udostępnia
statyczne metody do tworzenia, sprawdzania poprawności oraz przemieszczenia się
katalogów. Poniższa tabela przedstawia najważniejsze metody statyczne klasy Directory:
|
Nazwa metody
|
Zastosowanie
metody
|
| CreateDirectory()
|
Tworzy wszystkie
katalogi i podkatalogi określone przez parametr path
|
| GetCreationTime()
|
Zwraca i ustawia
czas tworzenia katalogu
|
| GetDirectories()
|
Pobiera określone
katalogi
|
| GetLogicalDrives()
|
Zwraca nazwę napędu
logicznego
|
| Move()
|
Przemieszcza
katalog i jego zawartość do miejsca określonego przez path
|
Powyższe metody są statyczne, a
więc nie trzeba tworzyć egzemplarza ich klasy tylko je wywoływać bezpośrednio.
Obok klasy
Directory, drugą
potężną klasą do manipulacji katalogami jest klasa
DirectoryInfo. Klasa
ta zawiera jedynie metody egzemplarza (nie ma bowiem żadnych metod
statycznych).
Poniższa tabela przedstawia
najczęściej używane przez programistów metody oraz właściwości klasy DirectoryInfo:
| Metoda lub
właściwość
|
Zastosowanie
metody
|
| Attributes
|
Właściwość, która
pobiera i ustawia atrybuty aktualnego pliku
|
| Exists
|
Właściwość, która
zwraca true, jeśli dany katalog istnieje
|
| FullName
|
Właściwość, która
zwraca pełną ścieżkę do katalogu
|
| Root
|
Zwraca fragment
ścieżki reprezentujący główny katalog
|
| Create()
|
Metoda, która
pozwala utworzyć nowy katalog
|
| CreateSubdirectory()
|
Pozwala utworzyć
podkatalog w określonej ścieżce
|
| Delete()
|
Pozwala usunąć
katalog/podkatalog
|
| GetDirectories()
|
Zwraca listę
podkatalogów
|
| GetFiles()
|
Zwraca listę
plików, które znajdują się w danym katalogu
|
| MoveTo()
|
Pozwala przenieść
katalog/podkatalog do odpowiedniego miejsca
|
Zastosujmy więc niektóre metody i
właściwości z powyższej tabeli w następującym przykładzie:
using System;
using System.IO;
namespace CentrumXP_19
{
class MojaKlasa
{
// definiujemy
zmienna poziom i ustawiamy ja na -1
int poziom = -1;
public static void Main(string[]
args)
{
MojaKlasa
mk = new MojaKlasa();
//wybieramy
poczatkowy podkatalog
string
mojaSciezka = "C:\\KatalogGlowny";
// definiujemy
obiekt typu DirectoryInfo
DirectoryInfo di = new DirectoryInfo(mojaSciezka);
//wywolanie
metody PrzegladKatalogow
mk.PrzegladKatalogow(di);
}
//metoda, ktora
wysietla informacje dotyczace odpowiedniego katalogu
public void
PrzegladKatalogow(DirectoryInfo dir)
{
//pierwszym
poziomem bedzie 0
poziom++;
// wyswietlamy
wszystkie katalogi i podkatalogi z okreslonej sciezki
Console.WriteLine("Poziom: {0}, nazwa: {1}", poziom,
dir.Name);
// wrzucamy do
tablicy wszystkie katalogi aktualnego folderu
DirectoryInfo[]
directories = dir.GetDirectories();
//przechodzimy
foreachem po wszystkich katalogach jakie aktualnie znajduja sie w tablicy
foreach (DirectoryInfo di in
directories)
{
//rekurencyjne
wywolanie metody PrzegladKatalogow()
PrzegladKatalogow(di);
}
// zmniejszamy
poziom
poziom--;
}
}
}
Powyższy programik to rekurencyjne
zagłębianie się w podkatalogi. Na początku określamy katalog, dla którego
będziemy wyświetlać wszystkie podkatalogi, jakie on posiada (w naszym przypadku
będzie to KatalogGlowny, leżący na dysku C, który będzie miał 3
katalogi, z których jeden będzie miał jeszcze jeden własny podkatalog).
Następnie dla tego głównego katalogu definiujemy obiekt di typu DirectoryInfo,
po czym wywołujemy na nim metodę PrzegladKatalogow(), przekazując do
niej utworzony wcześniej obiekt di. Zadaniem tej metody jest wyświetlenie
wszystkich katalogów, jakie posiada KatalogGlowny, a następnie pobranie
dla nich wszystkich ich podkatalogów. Liczba wszystkich podkatalogów aktualnego
katalogu jest wyświetlana za pomocą metody GetDirectories(), która
zwraca tablicę obiektów typu DirectoryInfo.
W instrukcji foreach
„przechodzimy” po wszystkich podkatalogach aktualnego katalogu i..wywołujemy na
nowo metodę PrzegladKatalogow() przekazując jej odpowiedni, aktualny
podkatalog. Taki mechanizm nazywamy rekurencją. Innymi słowy,
takie podejście powoduje rekurencyjne zagłębianie się metody w każdy
podkatalog, a następnie przejście do następnego podkatalogu z tego samego
poziomu.
Po skompilowaniu i uruchomieniu
powyższego przykładu otrzymamy następujące wyniki:

Potrafimy już używać obiektów DirectoryInfo,
a więc czas na poznianie drugiej ogromnej klasy, jaką jest niewątpliwie klasa File
oraz jej imienniczka FileInfo. Podobnie jak w przypadku Directory
i DirectoryInfo, tak i tutaj klasa File udostępnia statyczne
metody do tworzenia, sprawdzania poprawności oraz przemieszczenia się plików,
natomiast klasa FileInfo zawiera odpowiednie metody egzemplarza.
Poniższa tabela zawiera wybrane,
publiczne metody statyczne klasy File:
| Nazwa metody
|
Zastosowanie
metody
|
| Copy()
|
Metoda do
kopiowania istniejącego pliku do nowego pliku
|
| Create()
|
Tworzy nowy plik w
miejscu, które określiliśmy w parametrze path
|
| Delete()
|
Usuwamy określony
plik
|
| Exists
|
Właściwość, która
zwraca true, jeśli dany plik istnieje
|
| GetCreationTime()
|
Metoda do
pobierania daty utworzenia danego pliku
|
Natomiast poniższa tabela
prezentuje wybrane metody klasy FileInfo:
| Metoda lub
właściwość
|
Zastosowanie
metody
|
| Attributes
|
Właściwość, która
pobiera i ustawia atrybuty aktualnego pliku
|
| Exists
|
Właściwość, która
zwraca true, jeśli dany plik istnieje
|
| FullName
|
Właściwość, która
zwraca pełną ścieżkę do pliku
|
| LastWriteTime
|
Pobiera lub ustawia
czas ostatniego dostępu
|
| Lenght
|
Zwraca rozmiar
danego pliku
|
| Name
|
Zwraca nazwę danego
pliku
|
| Create()
|
Tworzy nowy plik
|
| Delete()
|
Usuwa dany plik
|
| Open()
|
Otwiera dany plik z
różnymi opcjami odczytu, zapisu etc.
|
Wykorzystajmy teraz kilka metod
oraz właściwości z powyższej tabeli i napiszmy program, który oprócz
wyświetlania wszsytkich katalogów (podkatalogów) będzie również zwracał listę
plików, jakie znajdują się w odpowiednich katalogach i podkatalogach:
using System;
using System.IO;
namespace CentrumXP_19
{
class MojaKlasa
{
// definiujemy
zmienna poziom i ustawiamy ja na -1
int poziom = -1;
public static void Main(string[]
args)
{
MojaKlasa
mk = new MojaKlasa();
//wybieramy
poczatkowy podkatalog
string
mojaSciezka = "C:\\KatalogGlowny";
// definiujemy
obiekt typu DirectoryInfo
DirectoryInfo di = new DirectoryInfo(mojaSciezka);
//wywolanie
metody PrzegladKatalogow
mk.PrzegladKatalogow(di);
}
//metoda, ktora
wysietla informacje dotyczace odpowiedniego katalogu
public void
PrzegladKatalogow(DirectoryInfo dir)
{
// pierwszym
poziomem bedzie 0
poziom++;
// wyswietlamy
wszystkie katalogi i podkatalogi z okreslonej sciezki
Console.WriteLine("Poziom: {0}, nazwa katalogu: {1}",
poziom, dir.Name);
// pobieramy
wszsytkie pliki, jakie znajduja sie w danym aktualnym katalogu
FileInfo[]
fi = dir.GetFiles();
//przechodzimy
foreachem po wszsytkich plikach jakie znajduja sie w danym aktualnym katalogu
foreach (FileInfo plik in fi)
{
Console.WriteLine("Poziom:
{0}, nazwa pliku: {1}, rozmiar: {2}, czas ostatniej modyfikacji: {3}",
poziom, plik.Name, plik.Length, plik.LastWriteTime);
}
// wrzucamy do
tablicy wszystkie katalogi aktualnego folderu
DirectoryInfo[]
directories = dir.GetDirectories();
//przechodzimy
foreachem po wszystkich katalogach jakie aktualnie znajduja sie w tablicy
foreach (DirectoryInfo di in
directories)
{
//rekurencyjne
wywolanie metody PrzegladKatalogow()
PrzegladKatalogow(di);
}
// zmniejszamy
poziom
poziom--;
}
}
}
Powyższy przykład wyświetla nie
tylko listę wszystkich katalogów oraz podkatalogów z określonej ścieżki, ale
również listę wszystkich plików, jakie znajdują się w tych folderach. W tym
celu zdefiniowaliśmy sobie tablicę przechowującą obiekty FileInfo (listę
plików) aktualnego katalogu (podkatalogu), a następnie za pomocą instrukcji
foreach przechodzimy po wszystkich tych plikach i wyświetlamy odpowiednie na
ich temat informacje.
Po uruchomieniu powyższego
przykładu otrzymamy następujące wyniki:

Na koniec napiszemy program,
który będzie podsumowaniem wiedzy, jaką zdobyliśmy dzisiaj oraz tydzień temu.
Nasz program będzie tworzył na dysku C:\ naszego komputera folder a w nim plik,
w którym będzie można napisać komentarz na temat portalu CentrumXP. Następnie z
pliku tego będziemy odczytywać wpisany tekst i wyświetlać na ekranie komputera:
using System;
using System.IO;
namespace CentrumXP_19
{
class
MojaKlasa
{
static void Main(string[] args)
{
//tworzymy
katalog wraz z plikiem
MojaKlasa
mk = new MojaKlasa();
Console.WriteLine(@"Podaj nazwę folderu jaki chcesz stworzyć na dysku
C:\");
string nazwaFolderu = Console.ReadLine();
mk.NowyFolder(@"C:\" + nazwaFolderu);
Console.WriteLine("Stworzono folder: {0}", nazwaFolderu);
Console.WriteLine(@"Podaj nazwę pliku jaki chcesz stworzyć w folderze:
{0}:", nazwaFolderu);
string nazwaPliku = Console.ReadLine();
FileStream fs = new FileStream(@"C:\" + nazwaFolderu + @"\" + nazwaPliku, FileMode.Create);
//wpisujemy do
pliku tekst
Console.WriteLine("Napisz swój komentarz na temat portalu
CentrumXP:");
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(Console.ReadLine());
sw.Close();
Console.WriteLine("Twój komentarz został zapisany do pliku: {0}",
nazwaPliku);
//uruchamiamy
metode, ktora odczyta z pliku wpisany komentarz
DirectoryInfo di = new DirectoryInfo(@"C:\" + nazwaFolderu);
mk.MojaMetoda(di);
}
void NowyFolder(string
sciezka)
{
DirectoryInfo di = new
DirectoryInfo(sciezka);
di.Create();
}
void MojaMetoda(DirectoryInfo
dirInfo)
{
string mojeDaneOdczyt = string.Empty;
FileInfo[] fileInfo = dirInfo.GetFiles();
foreach (FileInfo fi in fileInfo)
{
FileStream fs = new FileStream(fi.FullName, FileMode.Open);
StreamReader sr = new
StreamReader(fs);
Console.WriteLine("Odczytujemy Twój komentarz.");
Console.WriteLine("Twój komentarz to:");
while
((mojeDaneOdczyt = sr.ReadLine()) != null)
{
Console.WriteLine(mojeDaneOdczyt);
}
sr.Close();
}
}
}
}
Powyższy przykład jest
podsumowaniem poznanych przez nas dotychczas metod oraz właściwości, jakie
najczęściej używane są przez programistę w czasie wykonywania różnorakich
operacji wejścia – wyjścia. Mamy nadzieję, że przedstawione przez nas podstawy
na w/w temat przyczynią się do rozpoczęcia ich używania w naszych programach
oraz sprawią, że nie będą dla nas obce nawet w trudniejszych przykładach.
Po uruchomieniu programu
otrzymamy następujący przykładowy ekran:

Za tydzień opowiemy sobie o
atrybutach oraz mechaniźmie refleksji w języku obiektowym C# 2.0.