C# STRUMIENIE


W tej lekcji nauczysz się jak zapisywać dane do pliku, oraz jak je odczytywać. Jednak zanim to przećwiczymy zapoznamy się trochę z teorią. W C# zapis np. do pliku odbywa się za pomocą strumieni, zatem czym są te strumienie? Spróbujemy to sobie jakoś obrazowo wytłumaczyć, strumień z zasady gdzieś się zaczyna i kończy, czyli ma początek i koniec, początkiem strumienia w C# jest to co np. wysyła dane, a końcem miejsce docelowe danych (czyli odbiorca np. Plik na dysku, lub ekran monitora), jak już się domyślasz w strumieniu coś płynie, w C# są to dane, dlatego często się mówi np. Przepływ danych, aby zacząć coś wysyłać do czegoś trzeba na samym początku jakby utworzyć taki strumień między odbiorcą a adresatem i po wysłaniu danych czy ich odebraniu należy ten strumień zamknąć. Ok. teraz zaczniemy korzystanie z strumieni które pozwalają na obsługę plików, a na samym początku są to strumienie bajtowe.

Skorzystamy tutaj z klasy FileStream która to jest zadeklarowana w przestrzeni nazw System.IO Przejdźmy zatem do ogólnej deklaracji FileStream:

FileStream nazwa = new FileStream(string ścieżka, FileMode tryb, FileAccess jak);

Gdzie ścieżka jest zapisem ścieżki pliku, np. „tekst.txt”, „c:\\opowiadanie.txt”. FileMode określa co ma być zrobione z plikiem w podanej ścieżce czy ma być otwarty czy utworzony, oto wszystkie wartości FileMode:
FileMode.Open – Otwiera plik, jeżeli taki nie istnieje zgłasza wyjątek.

FileMode.OpenOrCreate – Otwiera plik, jeżeli taki nie istnieje tworzy go.

FileMode.Append – Dopisywanie na koniec pliku.

FileMode.CreateNew – Tworzy nowy plik, jeżeli już istnieje ten plik zostanie zgłoszony wyjątek.

FileMode.Create – Tworzy nowy plik, jeżeli plik już istnieje zostanie zastąpiony.

FileMode.Truncate – Otwiera plik i kasuje jego zawartość do zera, jeżeli plik nie istnieje zgłasza wyjątek.

FileAccess określa tryb dostępu do pliku, a oto poniższe wartości:

FileAccess.Read – Plik tylko do odczytu.

FileAccess.Write – Plik tylko do zapisu.

FileAccess.ReadWrite – Plik do odczytu i zapisu.

Przejdźmy zatem do prostego przykładu w którym to odczytamy sobie plik, dla tego przykładu utwórz na dysku C: plik o nazwie tekst.txt

Początek kodu:


using System;
using System.IO;


class Pokaz
{
public static void Main()
{
FileStream plik;
int w ;
char znak ;


try
{
plik = new FileStream(„c:\\tekst.txt”, FileMode.Open);
}
catch (FileNotFoundException)
{
Console.WriteLine(„* BŁĄD * Brak pliku tekst.txt”);
return;

}


do
{
w = plik.ReadByte();
if(w>0)
Console.Write((char)w);
} while (w > 0);

plik.Close();

Console.WriteLine(„\n\n”);

}
}

Koniec kodu:

Zastosowanie try  nie powinno cię dziwić, jeżeli taki plik nie istnieje zostanie zgłoszony wyjątek FileNotFoundException. Z tego tytułu że ten typ strumienia jest buforowany bajtowo to każdy znak w pliku trzeba odczytać osobno, jako osobny bajt. Jak widzisz używamy w tym celu metody ReadByte() która to zwraca nam wartość danego znaku. Którzy następnie za pomocą rzutowania przekształcamy na znak char i wyświetlamy. Metoda ta nam zwróci -1 jeżeli napotka koniec pliku dlatego musimy się też tutaj uchronić przed wyświetleniem końca plik, poprzez if. Tak samo jest z zapisem każdy bajt trzeba zapisać osobno, jest to uciążliwa metoda, ale prześledź sobie przykład zapisu do pliku:

Początek kodu:
using System;
using System.IO;


class Pokaz
{
public static void Main()
{
FileStream plik;
int w ;
char[] znaki = {‘T’,'o’,’ ‘,’j',’e',’s',’t',’ ‘,’t',’e',’k',’s',’t'} ;


try
{
plik = new FileStream(„c:\\zapis.txt”, FileMode.Create);
}
catch
{
Console.WriteLine(„* BŁĄD * Podczas zapisu do zapis.txt”);
return;

}


for (int i = 0; i <= znaki.Length – 1; i++)
{
plik.WriteByte((byte)znaki[i]);
}


plik.Close();


Console.WriteLine(„\n\n”);


}

}

Koniec kodu:

Kiedy już poznałeś podstawy pora zapoznać się ze strumieniami znakowymi, do których to nie trzeba przesyłać kolejnych bajtów tylko możemy od razu wysyłać/odbierać całe string-i jako na przykład całe linie. Dzielimy je na strumienie zapisu i strumienie odczytu, przejdźmy zatem do deklaracji obydwóch:

Strumień zapisu:

StreamWriter nazwa = new StreamWriter(Filestream plik);
Strumień odczytu:

StreamReader nazwa = new StreamReader(FileStream plik);

Istnieje też druga deklaracja w której to zamiast FileStream mamy parametr typu string w którym to przesyłamy ścieżkę do pliku, ja jednak polecam korzystanie z tych przeładowań konstruktorów podanych powyżej. Dzięki tym strumieniom mamy bardzo ułatwione operacje na plikach. Zobacz jak teraz wygląda prosto odczyt z pliku.

Początek kodu:
using System;
using System.IO;


class Pokaz
{
public static void Main()
{
FileStream plik;
string odczyt;


try
{
plik = new FileStream(„c:\\tekst.txt”, FileMode.Open);
}
catch
{
Console.WriteLine(„* BŁĄD * Podczas zapisu do zapis.txt”);
return;

}


StreamReader p = new StreamReader(plik);


odczyt = p.ReadLine();


do
{
Console.WriteLine(odczyt);
odczyt = p.ReadLine();
} while (odczyt != null);


p.Close();
plik.Close();


Console.WriteLine(„\n\n”);


}

}

Koniec kodu:

Z zapisem jest jeszcze prościej po prostu stosujesz tylko p.WriteLine(string); nic prostszego pamiętaj tylko aby potem pozamykać wszystkie strumienie. Jest coś takiego jak plik o dostępie swobodnym, czyli pozwala nam on ustawić znak czytania/zapisu w dowolnym miejscu w pliku, skorzystamy tutaj z metody Seek. Której to deklaracja wygląda następująco:

plik.Seek(long pozycja, SeekOrgin odniesienie) ;
Gdzie pozycja jest liczbowym określeniem pozycji znaku, a SeekOrgin określa odniesienie względem jakiego ma być uznana pozycja znaku, a to są wartości jakie może posiadać SeekOrgin:

SeekOrgin.Begin – Początek pliku

SeekOrgin.Current – Aktualna pozycja

SeekOrgin.End – Koniec pliku

IO posiada jeszcze wiele metod i wiele własności które ułatwiają nam pisanie programów, postaraj się teraz na własną  rękę zapoznać się z resztą składników tych klas.

Warto wspomnieć jeszcze o czymś takim jak przekierowanie standardowych strumieni. To znaczy możemy przekierować strumień który wyświetla jakiś tekst na ekranie Console.WriteLine() na przykład do pliku. Można to zrobić w następujący sposób.

Console.SetIn(TextWriter plik);
Dzięki tej metodzie każde użycie WriteLine nie spowoduje wyświetlenie tekstu na ekranie tylko zapisanie go do pliku. TextWriter jest klasą bazową dla StreamWriter więc bez problemu możesz ją wykorzystać. Możesz jeszcze przekierować dwa strumienie:

SetOut – Powoduje że każde użycie readline powoduje odczyt nie z konsoli tylko z pliku.

SetError – powoduje że każdy błąd nie będzie wyświetlany w konsoli tylko zapisywany do pliku.