Trzecim bytem jaki zostanie przedstawiony podczas opowiadanek o obsłudze plików będzie "FileStream". "FileStream" w języku C# jest takim punktem startowym dla wykonywania podstawowych operacji. Dzięki wspomnianej klasie, możemy sobie wybrać w jaki sposób chcemy operować na pliku podając jeden z trybów dostępu. Ale szczegóły tego procederu opiszemy sobie już w środku.
Tweet |
"FILESTREAM" W JĘZYKU C# JESZCZE JEDNYM SPOSOBEM OBSŁUGIWANIA PLIKÓW
Był już opis "FileInfo" dla plików i "DirectoryInfo" dla katalogów. Wydawać by się mogło, że oto ukończyliśmy omawianie wszystkich podstawowych rzeczy przeznaczonych do obsługi plików. A tu niespodzianka! Jest jeszcze kilka bytów, które mogą się Wam przydać. Nie napiszę, że przydadzą się na pewno, bo uciekłbym się do kłamstwa. Muszę założyć, że kiedyś jednak ta wiedza stanie się przydatna więc siłą rzeczy muszę o tym napisać.
"FileStream" w języku C# w odróżnieniu od poprzednich klas, nie jest częścią "FileSystemInfo" ponieważ charakteryzuje się inną metodyką obsługiwania plików. Tamte dwie poprzednie dotyczyły obsługi plików i katalogów "na zewnątrz". Tworzenie i usuwanie dotyczyło samego pliku. Wydobywanie informacji o nim dotyczyło samego pliku. "FileStream" zaś pozwala na edytowanie...zawartości pliku, czyli modyfikacje dotyczącą wnętrza pliku! Możecie się już domyślać jakie operacje zostaną zawarte w opisywanej klasie. Mianowicie dopisywanie do pliku, nadpisywanie pliku etc. Tego typu operacje, choć samo tworzenie i usuwanie także jest dostępne.
WŁAŚCIWOŚCI KLASY "FILESTREAM"
A teraz właściwości, kochani. Oto zbiór jakim dysponuje "FileStream" w języku C#:
Nazwa | Znaczenie | Modyfikowalna |
CanRead | Ustalenie czy bieżący strumień obsługuje odczyt | nie |
CanSeek | Ustalenie czy bieżący strumień obsługuje szukanie | |
CanWrite | Ustalenie czy bieżący strumień obsługuje zapisywanie | |
Handle* | Pobranie obsługi plików zapewnianej przez system operacyjny w postaci wskaźnika | |
IsAsync | Ustalenie czy plik otwarto w sposób asynchroniczny | |
Length | Pobranie długości strumienia w bajtach | |
Name | Pobranie ścieżki bezwzględnej pliku otwartego przez obiekt "FileStream" | |
Position | Pobranie lub ustawienie pozycji strumienia | tak |
SafeFileHandle | Zwrócenie obiektu typu "SafeFileHandle" będącego wskaźnikiem do obsługi plików zapewnianej przez system operacyjny | nie |
* - uznane przez dokumentację za przestarzałe, używać zamiast tego "SafeFileHandle"
METODY KLASY "FILESTREAM"
A jakimi metodami może się pochwalić "FileStream" w języku C#? Wszystkie patrzały zerkają niżej:
Nazwa | Znaczenie |
BeginRead | Rozpoczęcie asynchronicznej operacji odczytu. |
BeginWrite | Rozpoczęcie asynchronicznej operacji zapisu. |
Close | Zamknięcie strumienia (bardzo ważnym jest, żeby ZAWSZE na końcu wywołać tę metodę; inaczej plik może się nie ukazać w katalogu i nie będzie możliwe wykonywanie na nim operacji!). |
Dispose | Zwolnienie niezarządzanych zasobów (parametr "boolowski" pozwala także zwolnić te zarządzane). |
EndRead | Zakończenie asynchronicznej operacji odczytu. |
EndWrite | Zakończenie asynchronicznej operacji zapisu. |
Flush | Czyszczenie buforów strumienia i zapis danych bufora do pliku. |
Lock | Zabezpieczenie przed otwieraniem i zapisem do pliku przez inne procesy w systemie operacyjnym. |
Read | Odczyt bloku bajtów ze strumienia i zapis w podanym buforze. |
ReadByte | Odczyt pojedynczego bajta ze strumienia i przeniesienie pozycji o jeden bajt do przodu. |
Seek | Ustawienie pozycji strumienia na podaną wartość. |
SetLength | Ustawienie długości strumienia w bajtach. |
Unlock | Zdjęcie nałożonego wcześniej zabezpieczenia w wyniku wywołania metody "Lock". |
Write | Zapis sekwencji bajtów do strumienia i przejście do aktualnej pozycji o podaną liczbę bajtów do zapisu. |
WriteByte | Zapis pojedynczego bajta do aktualnej pozycji w strumieniu. |
PRZYKŁAD KODU ŹRÓDŁOWEGO
Przedstawię dwa przykłady kodów. Jeden do zapisu danych, drugi do odczytu. "FileStream" w języku C# może być dopasowane zarówno do jednej czynności, jak i do drugiej.
ZAPIS DO PLIKU
string filename = "data.txt";
FileStream fs = new FileStream(filename, FileMode.Create);
for (byte i = 1; i <= 50; ++i)
{
fs.WriteByte(i);
}
fs.Close();
ODCZYT Z PLIKU
string filename = "data.txt";
FileStream fs = new FileStream(filename, FileMode.Open);
int count = 50;
byte[] bytes = new byte[count];
fs.Read(bytes, 0, count);
for (byte i = 1; i <= count; ++i)
{
//Console.WriteLine(fs.ReadByte()); // przy użyciu tej metody, tworzenie tablicy "bytes" i wywołanie metody "Read" nie będą potrzebne, można usunąć
Console.WriteLine(bytes[i - 1]);
}
fs.Close();
Widać, że w drugim kodzie zawarłem obie instrukcje, a jedna z nich została zakomentowana. To dlatego, że odczyt za pomocą "FileStream" w języku C# można wykonać na dwa sposoby: albo przy użyciu funkcji "ReadByte" odczytywać za każdym razem po małej porcji danych bajt po bajcie korzystając z pętli "for", albo zainicjować tablicę typu "byte", przydzielić jej identyczną liczbę komórek (o tym mankamencie więcej za chwilę), wywołać metodę "Read" podając odpowiednie parametry (tablica bajtów, w której będą składowane dane, przesunięcie kursora o N bajtów i liczbę bajtów do wydobycia) i wyświetlać każdy argument, również przy użyciu pętli "for" albo jakiejś innej. Ale to jeszcze nie koniec przedstawianego wątku...
SPOSÓB NA NIEREGULARNĄ LICZBĘ DANYCH
Jest mały problemik dotyczący wypisywania. Przy próbie odczytu musimy podać KONKRETNĄ liczbę bajtów! Sytuacja jednak nie jest do końca taka beznadziejna, bowiem metoda "ReadByte" zwraca wartość -1 jeśli nie znajduje żadnych kolejnych danych do wydobycia. Stąd wniosek dla kumatych głów, że mając na względzie wyżej podaną informację, można wykorzystać pętlę "while" do odczytu nieregularnej wielkości danych wykorzystując w instrukcji warunkowej badanie wartości "ReadByte":
while (fs.ReadByte() != -1)
{
// instrukcje
}
Ponieważ chcemy zrobić z danych użytek, lepiej jest przechować tymczasowo wydobyty bajt w zmiennej:
int i;
while ((i = fs.ReadByte()) != -1)
{
// instrukcje
}
Metoda zwraca "integer" więc nie ma problemów z podstawieniem do liczby całkowitej "klasycznej". Jest jednak niestety bardziej druzgocąca wada. "FileStream" w języku C# obsługuje tylko bajty! W jedną i w drugą stronę wszystko kręci się wyłącznie w formie bajtowej. Nie mamy prawa wstawić sobie np. łańcucha znaków jako takiego (w jednym kawałku) i go sobie potem odczytać także jako łańcuch znaków. Wrócimy do tego dylematu później, wraz z zaprezentowaniem klasy pomocniczej, "StreamReader".
![]() |
Klasa "FileStream" jest zdolna wykonywać podstawowe operacje WEWNĄTRZ pliku. Ze względu na naturę danych, potrafi posługiwać się wyłącznie bajtami!
Dobiegła końca epicka przygoda o klasie "FileStream" w języku C# przeznaczonej do "grzebania" w pliku. W kolejnej części o obsłudze plików zajmiemy się trybami dostępu do pliku.