Trzecim bytem jaki zostanie przedstawiony podczas opowiadanek o obsłudze plików w "CSharpie" 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 :D! Jest jeszcze kilka odmian, 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 :O! 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, lepiej używać "SafeFileHandle"
METODY KLASY "FILESTREAM"
A jakimi metodami może się pochwalić "FileStream" w języku C#? Wszystkie patrzały zerkają niżej :D:
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 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 :O! 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 opowieść 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.