background image

Odczytywanie i zapisywanie 
plików na serwerze WWW 

Odczyt i zapis plików jest niezwykle waŜnym zagadnieniem ASP.NET. W poprzedniej części 
ksiąŜki tworzyłeś juŜ strony ASP.NET wykorzystujące pliki zewnętrzne (na przykład plik 

config.web

, kod obsługi formularzy, pliki XML, itp.), jednak w tym rozdziale dowiesz się znacznie 

więcej o sposobie w jaki inne typy plików mogą powiększyć moŜliwości funkcjonalne aplikacji 
ASP.NET. 

Istnieje bardzo wiele moŜliwości wykorzystania plików — bynajmniej nie ograniczają się one do 
przechowania danych zewnętrznych. W tym rozdziale omówione zostaną następujące zagadnienia: 

 

Sposoby uŜycia plików w ASP.NET oraz gdzie pliki te będą widziane. 

 

Sposoby dołączania plików do stron ASP.NET. 

 

Sposoby dostępu do właściwości plików i folderów. 

 

Sposoby otwierania, odczytu i zapisu informacji w plikach. 

 

Sposoby dostarczania wydzielonych obszarów przechowywania danych dla kaŜdego z 
uŜytkowników. 

Wykorzystanie plików w ASP.NET 

Dzięki środowisku .NET wykorzystanie plików zewnętrznych (czyli plików z rozszerzeniem inne 
niŜ 

.aspx

) w ASP.NET jest bardzo łatwe. W rzeczywistości, pliki te są konieczne, by aplikacje 

ASP.NET działały poprawnie. Do takich niezbędnych plików moŜna zaliczyć 

web.config

 oraz 

global.asax

 kontrolujące sposób działania aplikacji. 

Pliki zewnętrzne moŜna takŜe wykorzystać do zwiększenia moŜliwości funkcjonalnych ASP.NET. 
Poznałeś juŜ kilka takich plików, na przykład własne elementy sterujące oraz przestrzenie nazw 
kompilowane do postaci bibliotek DLL. Pliki te zwiększają moŜliwości funkcjonalne tworzonych 
aplikacji ASP.NET, a jednocześnie umoŜliwiają zachowanie prostoty kodu źródłowego stron 
ASP.NET. 

APS.NET pozwala takŜe na korzystanie z plików, które w ogóle nie stanowią części aplikacji lecz 
mogą się w niej przydać. Do plików tego typu moŜna zaliczyć pliki zawierające informacje 
tekstowe, importowane pliki z nagłówkami informacyjnymi, pliki zawierające informacje o 
aplikacji, pliki z Ŝyciorysami, oraz wszelkie inne pliki, które w jakikolwiek sposób mogą się 
okazać przydatne. ASP.NET pozwala na dostęp i wykorzystanie całego systemu plików serwera, a 
zatem moŜliwości są ogromne. 

Doł

ą

czanie zawarto

ś

ci plików zewn

ę

trznych 

Jednym ze sposobów wykorzystania plików w ASP.NET jest, tak zwane, 

dołączanie plików

Sposób ten przypomina pobranie zawartości jednego pliku i umieszczenie jej wewnątrz drugiego 

background image

pliku; na szczęście jednak, programista nie musi tego robić samemu. Sposoby przedstawione w 
kilku kolejnych podrozdziałach pokazują róŜne metody dołączania plików dostępne w ASP.NET. 

Server-Side Includes 

Server-Sice Includes (dołączanie plików po stronie serwera, w skrócie SSI) jest sposobem 
oddzielania kodu od tworzonej strony. Metoda jest przydatna w sytuacjach gdy chcemy 
wielokrotnie uŜywać wybranego fragmentu kodu, bądź uprościć edycję stron. 

Składnia pozwalająca na dołączanie kodu tą metodą ma następującą postać: 

<!--#include file="nazwaPliku"--> 
 

lub  

<!--#include virtual="nazwaPliku"--> 
 

Słowo kluczowe 

virtual

 słuŜy do określenia nazwy dołączanego pliku przy wykorzystaniu 

ś

cieŜki wirtualnej, natomiast słowo kluczowe 

file

 umoŜliwia podanie ścieŜki dostępu do pliku w 

lokalnej strukturze folderów. Na przykład, jeśli byś chciał dołączyć zawartość pliku o adresie 

http://twoj.serwer.com.pl/includes/plik1.aspx

 do strony ASP.NET o adresie 

http://twoj.serwer.com.pl/folder1/folder2/strona.aspx

, mógłbyś w tym celu wykorzystać jedno z 

dwóch poniŜszych poleceń 

#include

<!--#include file="../../includes/plik1.aspx"--> 
 

lub  

<!--#include virtual="/includes/plik1.aspx"--> 
 

Zwróć uwagę, iŜ uŜyte polecenie 

#include file

 będzie miało róŜną postać w zaleŜności do 

połoŜenia strony, w której będzie umieszczana zawartość dołączanego pliku. Określenie pliku 
wykorzystywane w takim poleceniu nazywamy względną ścieŜką dostępu do pliku. UŜywanie 
takich ścieŜek moŜe być denerwujące, zwłaszcza gdy strony wykorzystujące polecenie 

#include

 

znajdują się w róŜnych folderach. Z tego właśnie powodu ASP.NET umoŜliwia takŜe dołączanie 
plików na podstawie bezwzględnych ścieŜek dostępu — słuŜy do tego polecenie 

#include 

virtual

 przedstawione na drugim przykładzie. UmoŜliwia ono określenie połoŜenia dołączanego 

pliku w sposób niezaleŜny od połoŜenia pliku, do którego zostanie on dołączony. 

Umieśćmy zatem nagłówek w pliku, który będziemy mogli dołączyć do wielu róŜnych stron 
ASP.NET. W tym celu, w pierwszej kolejności naleŜy stworzyć stronę ASP.NET o nazwie 

header.aspx

 i umieścić w niej następujący kod: 

<a href="index.aspx"><img src="header.gif" alt="Strona główna"></a><hr> 
<a href="index.aspx">Strona główna</a> <a href="logout.aspx">Wyjd

ź

</a> 

 

Nie naleŜy umieszczać w tym pliku Ŝadnych innych znaczników, jak na przykład elementy 

<form>

 — zostaną one umieszczone w kodzie strony, do której plik 

header.aspx

 będzie 

dołączany. Kolejną czynnością będzie stworzenie w tym samym folderze kolejnej strony 
ASP.NET i dołączenie do niej nagłówka: 

<script language="VB" runat="server"> 
   sub Page_Load(obj as object, e as eventargs) 
   end sub 
</script> 
 
<html><body> 
  <!--#include file="header.aspx"--> 
  Witamy! 
</body></html> 
 

ASP.NET wstawi zawartość pliku 

header.aspx

 

zanim

 zostaną przetworzone jakiekolwiek 

polecenia ASP.NET. Z tego względu, gdy strona będzie juŜ gotowa do wykonania, środowisko 
ASP.NET będzie uwaŜało iŜ jej kod ma następującą postać: 

<script language="VB" runat="server"> 
   sub Page_Load(obj as object, e as eventargs) 
   end sub 

background image

</script> 
 
<html><body> 
<a href="index.aspx"><img src="header.gif" alt="Strona główna"></a><hr> 
<a href="index.aspx">Strona główna</a> <a href="logout.aspx">Wyjd

ź

</a> 

  Witamy! 
</body></html> 
 

Postać strony, po wyświetleniu w przeglądarce, przedstawiłem na rysunku 13.1. 

 

 

Rysunek 13.1. 

Zawartość plików dołączanych po stronie serwera jest traktowana tak, jak gdyby 

stanowiła część wykonywanej strony ASP.NET 

 

Notatka 
Nale

Ŝ

y  pami

ę

ta

ć

Ŝ

e  wszystkie  opisywane  czynno

ś

ci  s

ą

  wykonywane  na  serwerze,  zanim 

jakiekolwiek  informacje  zostan

ą

  przesłane  do  przegl

ą

darki.  Zawarto

ść

  wszystkich  plików  jest 

ł

ą

czona  ze  sob

ą

  na  serwerze  zanim  zostanie  wykonany  jakikolwiek  kod  ASP.NET  i  zanim 

cokolwiek zostanie przesłane do klienta. Dzi

ę

ki temu, wywołania metody 

Response.Redirect

 

b

ę

d

ą

 działa

ć

 poprawnie. 

Polecenia 

#include

 moŜna umieszczać w dowolnych miejscach stron ASP.NET, oznacza to, iŜ 

przedstawiony w powyŜszym przykładzie nagłówek, równie dobrze mógłby być dołączony jako 
stopka. W dołączanym pliku moŜna by takŜe umieścić znaczniki 

<html>

 oraz 

<body>

, jak 

równieŜ elementy sterujące wykonywane na serwerze. 

Ostrze

Ŝ

enie 

Domy

ś

lnie  polecenie 

#include

  mo

Ŝ

na  u

Ŝ

ywa

ć

  wył

ą

cznie  w  plikach  o  rozszerzeniach 

.shtml

.shtm

.stm

.asp

.asa

.asax

 oraz 

.aspx

. Polecenie to umieszczone w kodzie strony HTML nie 

zostanie  przetworzone.  Rozszerzenia  plików  obsługuj

ą

cych  mechanizm  Server-Side  Includes 

mo

Ŝ

na okre

ś

la

ć

 w Internet Services Managerze — programie zarz

ą

dzaj

ą

cym serwerem IIS 5.0. 

Server-Side Includes a inne sposoby doł

ą

czania plików 

MoŜesz się zastanawiać nad róŜnicą pomiędzy technologią Server-Side Includes a elementami 
sterującymi tworzonymi przesz uŜytkowników. Oba te rozwiązania moŜna wykorzystywać w tych 
samych celach — od wydzielania fragmentów interfejsu uŜytkownika. RóŜnica pomiędzy nimi 
polega na tym, iŜ elementy sterujące słuŜą wyłącznie do tworzenia fragmentów interfejsu 
uŜytkownika, natomiast SSI moŜna uŜywać w róŜnych celach, między innymi do wydzielenia i 
zapisania w jednym miejscu często wykorzystywanych funkcji i stałych. 

background image

Zazwyczaj, w przypadku wydzielania elementu interfejsu uŜytkownika, lepiej jest posłuŜyć się 
elementem sterującym, gdyŜ moŜna w nim wykorzystać elementy programistyczne; SSI nie daje 
tej moŜliwości. 

 

Tak 

Nie 

SSI naleŜy się posługiwać jeśli chcemy 
dołączać do tworzonych stron często 
wykorzystywane elementy programistyczne, 
takie jak klasy lub funkcje. 

Nie naleŜy uŜywać SSI gdy chcemy dołączyć do 
strony wyłącznie element interfejsu 
uŜytkownika. W takim przypadku lepszym 
rozwiązaniem będzie wykorzystanie elementów 
sterujących tworzonych przez uŜytkownika. 

Inne sposoby doł

ą

czania plików 

Ś

rodowisko ASP.NET udostępnia takŜe inne sposoby dołączania plików. Większość z nich została 

juŜ przedstawiona we wcześniejszych częściach ksiąŜki. Kod obsługi formularzy omówiłem w 
rozdziale 6, pt.: „Ciąg dalszy wiadomości na temat tworzenia formularzy internetowych”. 
Informacje na temat dyrektywy 

Import

 znajdziesz natomiast w rozdziale 2 — pt.: „Tworzenie 

stron ASP.NET”. I w końcu, w rozdziale 5. — pt.: „Podstawowe wiadomości o tworzeniu 
formularzy internetowych” — opisałem tworzenie elementów sterujących uŜytkownika. 

Wszystkie te metody róŜnią się sposobem implementacji, lecz kaŜda z nich zapewnia moŜliwość 
dołączania do stron ASP.NET zawartości innych plików. 

Dost

ę

p do plików 

Przestrzeń nazw 

System.IO

 udostępnia wiele moŜliwości funkcjonalnych, z których moŜna 

korzystać przy tworzeniu stron ASP.NET. Do moŜliwości tych naleŜy zaliczyć odczytywanie i 
zapisywanie plików, tworzenie i usuwanie folderów oraz sprawdzanie atrybutów plików i 
folderów. MoŜliwości funkcjonalne udostępniane przez tę przestrzeń nazw pozwalają takŜe na 
wykonywanie czynności w odpowiedzi na zdarzenia związane z systemem plików, takie jak 
stworzenie lub usunięcie folderu przez innego uŜytkownika. 

Pliki, strumienie, czytelnicy i pisarze 

Nim zaczniemy poznawać klasy dostępne w przestrzeni nazw 

System.IO

 oraz operować na 

plikach, naleŜy przedstawić róŜnicę pomiędzy plikami i strumieniami. Zagadnienie to jest waŜne, 
gdyŜ zarówno pliki jak i strumienie są w ASP.NET czymś zupełnie innym. 

 

Nowe określenie 

Z technicznego punktu widzenia 

plik

 jest kolekcją danych, której nadano nazwę i zapisano w 

unikalnym miejscu na dowolnie długi okres czasu. Na przykład, pliki przechowywane na dysku 
twardym Twojego komputera posiadają nazwę i ścieŜkę dostępu, a moŜesz z nich korzystać w 
kaŜdej chwili gdy tylko będziesz tego potrzebować. MoŜesz wyobraŜać sobie plik jako pudełko 
zawierające róŜne rzeczy — realny obiekt. 

 

Nowe określenie 

Natomiast ze 

strumieniem

 nie jest skojarzona Ŝadna nazwa pliku, ścieŜka dostępu ani teŜ miejsce 

przechowywania. Strumień moŜe zostać wykorzystany do odczytania lub zapisu danych z 
dowolnego miejsca, na przykład pliku, sieci czy teŜ pamięci. A zatem strumień jest sposobem 
zapewnienia dostępu do dowolnych informacji, w tym takŜe do plików. Gdy otwierasz i 
odczytujesz zawartość pliku, w rzeczywistości jest przy tym wykorzystywany strumień. 

background image

Dostępnych jest wiele róŜnych typów strumieni, lecz wszystkie one są klasami potomnymi klasy 

Stream

Strumienie zapewniają binarny dostęp do danych — odczytują one nieprzetworzone informacje w 
formie zer i jedynek. Taki sposób dostępu do danych moŜe być przydatny, lecz w ASP.NET 
bardziej interesuje nas korzystanie z informacji zapisanych w kodzie Unicede — czyli z 
łańcuchów znaków, a nie ciągów zer i jedynek. 

Ś

rodowisko .NET udostępnia dwie klasy słuŜące właśnie do tego celu — 

TextReader

 oraz 

TextWriter

. Nie będę ich tu szczegółowo opisywał, jednak naleŜy wiedzieć iŜ dziedziczy po 

nich wiele innych klas. Przykładami klas potomnych kas 

TextReader

 oraz 

TextWriter

 są 

XmlTextReader

 oraz 

XmlTextWriter

 przedstawione w rozdziale 11., pt.: „UŜycie XML w 

ASP.NET”; a w tym rozdziale poznasz kilka kolejnych. 

A zatem dysponujemy juŜ dwiema niezaleŜnymi kategoriami klas — 

Stream

 oraz klasami 

potomnymi zapewniającymi dostęp do danych binarnych oraz 

TextReader

 i 

TextWriter

 (oraz 

ich klasami potomnymi) zapewniającymi dostęp do danych tekstowych. Poznając środowisko 
.NET bez Ŝadnych trudności moŜna określić do której z tych kategorii naleŜy interesująca nas 
klasa. Klasy i obiekty dziedziczące po klasie 

Stream

 mają zazwyczaj w nazwie słowo „

stream

”; 

na przykład: 

FileStram

MemoryStram

, itp. Z kolei klasy dziedziczące po klasach 

TextReader

 

oraz 

TextWriter

 mają zazwyczaj w nazwach słowa „

reader

” lub „

writer

”; na przykład: 

XmlTextReader

XmlTextWriter

, itd. 

Na szczęście dostępne są takŜe klasy umoŜliwiające konwersję danych binarnych na tekstowe. 
Dwie takie klasy — 

StreamReader

 oraz 

StreamWriter

 — niezwykle waŜne dla operacji na 

plikach w ASP.NET, zostaną opisane w dalszej części tego rozdziału. Rysunek 13.2 ilustruje 
wzajemne zaleŜności pomiędzy tymi wszystkimi klasami. 

Notatka 
Nie  nale

Ŝ

y  myli

ć

 strumieni,  czyli  klasy 

Stream

  oraz jej  klas  potomnych,  ze 

strumieniowaniem

Strumienie pozwalaj

ą

 na uzyskanie dost

ę

pu do miejsc w których przechowywane s

ą

 informacje, 

natomiast  strumieniowanie  to  metoda  dynamicznego  pobierania  danych,  kawałek  po  kawałku, 
gdy s

ą

 potrzebne. Strumienie mo

Ŝ

na porówna

ć

 z rzeczownikiem, natomiast strumieniowanie z 

czasownikiem — strumienie mog

ą

, cho

ć

 nie musz

ą

, by

ć

 strumieniowane. 

Nowe określenie 

Klasa 

Stream

 pozwala na 

asynchroniczny dostęp

 do danych. Oznacza to, Ŝe podczas 

wykonywania operacji na plikach, jednocześnie mogą być realizowane inne czynności. Na 
przykład, w przypadku zapisu informacji do bardzo duŜego pliku co prawdopodobnie będzie trwać 
dosyć długo, plik ten moŜna otworzyć asynchronicznie i zapisywać w nim dane w tle, a 
jednocześnie wykonywać kod, który przekieruje uŜytkownika w inne miejsce witryny. 

Przeciwieństwem dostępu asynchronicznego jest dostęp 

synchroniczny

. W tym przypadku, aby 

wykonać kolejny fragment kodu, realizacja poprzedniego fragmentu musi się zakończyć. 
Wykorzystanie tego trybu dostępu do plików moŜe doprowadzić do pogorszenia efektywności 
działania aplikacji. RóŜnice pomiędzy sposobem wykonywania operacji przy wykorzystaniu 
dostępu asynchronicznego i synchronicznego, zostały zilustrowane na rysunku 13.3. W tym 
rozdziale przedstawię wyłącznie synchronicznych dostęp do danych; więcej informacji na temat 
dostępu asynchronicznego znajdziesz w dokumentacji środowiska .NET. 

Okre

ś

lanie wła

ś

ciwo

ś

ci plików i folderów 

W tej części rozdziału skoncentrujemy się na czterech klasach: 

File

 i 

Directory

 oraz 

FileInfo

 oraz 

DirectoryInfo

. Pierwsze dwie z nich udostępniają metody słuŜące do 

tworzenia, modyfikacji oraz usuwania plików i folderów; a pozostałe — właściwości 
umoŜliwiające określanie atrybutów plików i folderów. Przykład wykorzystania obiektów tych 
klas przedstawiony został na listingu 13.1. 

 

Listing 13.1. 

Wyświetlanie informacji o plikach i folderach 

background image

1

 

<%@ Import Namespace="System.IO" %> 

2

 

<script language="VB" runat="server"> 

3

 

    

4

 

   sub Page_Load(obj as object, e as eventargs) 

5

 

      dim f as new FileInfo(Server.MapPath("listing1301.aspx")) 

6

 

 

7

 

      lblMessage.Text = "Informacje o pliku<br>" & _ 

8

 

         "<b>Nazwa: </b>" & f.Name & "<br>" & _ 

9

 

         "<b>

Ś

cie

Ŝ

ka: </b>" & f.DirectoryName & "<br>" & _ 

10

 

         "<b>Czas ostatniego dost

ę

pu: </b>" & f.LastAccessTime & _ 

11

 

            "<br>" & _ 

12

 

         "<b>Czas ostatniego zapisu: </b>" & f.LastWriteTime & _ 

13

 

            "<br>" & _ 

14

 

         "<b>Długo

ść

: </b>" & f.Length & " bajtów<p>" 

15

 

         

16

 

      'powrót do folderu nadrz

ę

dnego 

17

 

      dim dir as DirectoryInfo = f.Directory 

18

 

       

19

 

      lblMessage.Text += "Informacje o folderze<br>" & _ 

20

 

         "<b>Nazwa: </b>" & dir.Name & "<br>" & _ 

21

 

         "<b>Pełna nazwa: </b>" & dir.FullName & "<br>" & _ 

22

 

         "<b>Czas ostatniego dost

ę

pu: </b>" & dir.LastAccessTime & _ 

23

 

            "<br>" & _ 

24

 

         "<b>Czas ostatniego zapisu: </b>" & dir.LastWriteTime & _ 

25

 

            "<br>" & _ 

26

 

         "<b>Folder nadrz

ę

dny: </b>" & dir.Parent.Name & "<br>" 

27

 

       

28

 

   end sub 

29

 

 

30

 

</script> 

31

 

 

32

 

<html><body> 

33

 

   <asp:label id="lblMessage" runat=server/> 

34

 

</body></html> 

 

Analiza  

Zapisz powyŜszy kod w pliku o nazwie 

listing1301.aspx

. W pierwszym wierszu strony 

importowana jest dodatkowa przestrzeń nazwa — 

System.IO

.  W wierszu 5. tworzona jest nowa 

kopia obiektu 

FileInfo

 zawierającego informacje o naszym przykładowym pliku (dzięki temu 

moŜemy mieć pewność, Ŝe analizowany plik będzie istniał). Być moŜe przypominasz sobie, Ŝe w 
rozdziale 4., pt.: „Stosowanie obiektów ASP.NET w językach C# i VB.NET” została 
przedstawiona metoda 

Server.MapPath

, która odwzorowuje ścieŜkę wirtualną na fizyczną. W 

wierszach od 8. do 14. są wyświetlane informacje na temat analizowanego pliku. Wyniki 
wykonania powyŜszego przykładu przedstawione zostały na rysunku 13.4. 

 

background image

 

Rysunek 13.4. 

Wyświetlanie informacji o plikach i folderach 

 

W wierszu 17. tworzony jest obiekt 

DirectoryInfo

. Przy jego tworzeniu wykorzystana została 

właściwość 

Directory

, określająca folder w którym jest przechowywany analizowany plik. 

Następnie, w wierszach od 20. do 26. wyświetlane są informacje na temat wybranego folderu. Jak 
widać, obiekty 

FileInfo

 oraz 

DirectoryInfo

 mają wiele bardzo podobnych właściwości. 

 

Ostrze

Ŝ

enie 

Je

ś

li  wybrany  plik  nie  b

ę

dzie  istnie

ć

,  to  zostanie  zgłoszony  bł

ą

d.  Przy  wykorzystaniu  metody 

FileExists

 klasy 

File

, mo

Ŝ

na sprawdzi

ć

 czy wybrany plik istnieje czy nie. 

Podobnie,  przy  u

Ŝ

yciu  metody 

DirectoryExists

  klasy 

Directory

  mo

Ŝ

na  sprawdzi

ć

  czy  

wskazany folder jest poprawny. 

 

Obiekty klas 

File

 oraz 

Directory

 dysponują takŜe kolekcją 

Attributes

, za pośrednictwem 

której moŜna uzyskać dodatkowe informacje o pliku lub folderze, na przykład, czy jest on 
przeznaczony tylko do odczytu bądź ukryty. Wszystkie dostępne atrybuty zebrane zostały w tabeli 
13.1. 

 

Tabela 13.1. 

Atrybuty i wartości plików i folderów 

Atrybut 

Wartość 

Readonly 

Hidden 

System 

Directory 

16 

Archive 

32 

background image

Encrypted 

64 

Normal 

128 

Temporary 

256 

SparseFile 

512 

ReparsePoint 

1024 

Compressed 

2048 

OffLine 

4096 

NotContentIndexed 

8192 

 

Określając właściwości poszczególnych plików i folderów wartości te są do siebie dodawane. Na 
przykład, wykonanie poniŜszego kodu dla pliku 

listing1301.aspx

Response.Write(f.Attributes) 
 

spowoduje wygenerowanie łańcucha znaków 

"32"

, co oznacza iŜ plik ten jest archiwalny. Aby 

określić atrybuty pliku wystarczy zsumować wybrane wartości z tabeli 13.1 i przypisać je 
właściwości 

Attributes

. Na przykład, aby sprawić Ŝe nasz przykładowy plik będzie ukryty, 

systemowy, skompresowany, zaszyfrowany i nie indeksowany, wystarczy wykonać następującą 
instrukcję: 

f.Attributes = 10306 
 

Ostrze

Ŝ

enie 

Nie  mo

Ŝ

na  bezpo

ś

rednio  okre

ś

la

ć

  warto

ś

ci  poszczególnych  atrybutów.  Na  przykład,  poni

Ŝ

sza 

instrukcja: 

f.Attributes.Hidden = 2 

spowoduje  zgłoszenie  bł

ę

du.  Atrybut 

Hidden

  jest  bowiem  stał

ą

  i  nie  mo

Ŝ

na  go  modyfikowa

ć

Atrybuty  mo

Ŝ

na  zmienia

ć

  wył

ą

czenie,  za  po

ś

rednictwem  wła

ś

ciwo

ś

ci 

Attributes

,  na 

przykład: 

f.Attributes = 2 
 

 

Zapamiętanie wartości poszczególnych atrybutów moŜe przysporzyć duŜo problemów. A zatem, 
znacznie lepszym rozwiązaniem jest posługiwanie się nazwami odpowiednich stałych oraz 
operatorem 

BitOr

f.Attributes = FileAttributes.Hidden BitOr _ 
  FileAttributes.Compressed BitOr _ 
  FileAttributes.NotContentIndexed 
 

Wykonanie powyŜszego fragmentu kodu ma ten sam efekt co przypisanie właściwości 

Attributes

 wartości 

10306

BitOr

 to  jeden z grupy operatorów bitowych dostępnych w języku 

VB.NET; pozwala on na porównywanie wartości bitowych. Innymi operatorami zaliczającymi się 
do tej grupy są: 

BitAnd

BitNot

 oraz 

BitXor

. Aby określić czy dla analizowanego pliku jest 

ustawiony wybrany atrybut, naleŜy posłuŜyć się operatorem 

BitAnd

if f.Attributes BitAnd FileAttriubutes.Hidden > 0 then 
   Response.Write("Ukryty") 
end if 
 

PowyŜsze moŜliwości doskonale nadają się do wyświetlania informacji o jednym pliku bądź 
folderze. Co jednak zrobić, jeśli będziemy musieli wyświetlić więcej informacji dotyczących, na 
przykład, wszystkich plików w pewnym folderze? OtóŜ klasa 

DirectoryInfo

 udostępnia dwie 

metody — 

GetFiles

 oraz 

GetDirectories

 — które zwracają kolekcje obiektów 

FileInfo

 

oraz 

DirectoryInfo

. Przykład wykorzystania tych kolekcji przedstawiłem na listingu 13.2. 

 

background image

Listing 13.2. 

Wyświetlanie informacji o wszystkich plikach i folderach we wskazanym 

folderze 

1

 

<%@ Import Namespace="System.IO" %> 

2

 

<script language="VB" runat="server"> 

3

 

   sub Page_Load(obj as object, e as eventargs) 

4

 

      dim dir as new DirectoryInfo(Server.MapPath _ 

5

 

         ("/aspnetdlakazdego")) 

6

 

 

7

 

      DataGrid1.DataSource = dir.GetFiles("*.*") 

8

 

      DataGrid1.DataBind() 

9

 

       

10

 

      DataGrid2.DataSource = dir.GetDirectories 

11

 

      DataGrid2.DataBind() 

12

 

       

13

 

   end sub 

14

 

 

15

 

</script> 

16

 

 

17

 

<html><body> 

18

 

   <b>Informacje o plikach</b><br> 

19

 

   <asp:DataGrid id="DataGrid1" runat="server"  

20

 

      width="100%" 

21

 

      Font-Name="Arial"  

22

 

      Font-Size="10pt"  

23

 

      AlternatingItemStyle-Backcolor="#cccccc" 

24

 

      AutogenerateColumns="true" /> 

25

 

    

26

 

<p> 

27

 

<b>Informacje o folderach</b><br> 

28

 

<asp:DataGrid id="DataGrid2" runat="server"  

29

 

width="100%" 

30

 

Font-Name="Arial"  

31

 

Font-Size="10pt"  

32

 

AlternatingItemStyle-Backcolor="#cccccc" 

33

 

AutogenerateColumns="true" /> 

34

 

</body></html> 

 

Analiza 

W wierszu 7. pobierane są informacje o wszystkich plikach w bieŜącym folderze. W tym celu 
wywoływana jest metoda 

GetFiles("*.*")

, gdzie 

*.*

 oznacza dowolny łańcuch znaków, po 

którym jest umieszczona kropka, a po niej dowolny łańcuch znaków (czyli, przykładowo, 

listing1302.aspx

). Metoda ta zwraca kolekcję, a zatem bez problemów moŜna wykorzystać 

element sterujący 

DataGrid

, aby wyświetlić zawarte w niej informacje w wybrany przez nas 

sposób. W wierszu 10. wywoływana jest metoda 

GetDirectories

, która zwraca informacje o 

wszystkich folderach znajdujących się w bieŜącym folderze. Informacje te są wyświetlane 
podobnie jak informacje o plikach, przy wykorzystaniu elementu sterującego 

DataGrid

. Wyniki 

wykonania powyŜszego przykładu przedstawione zostały na rysunku 13.5. 

 

background image

 

Rysunek 13.5. 

Prezentacja informacji zawartych w kolekcjach plików i folderów 

 

Informacje z obu kolekcji moŜna by takŜe pobrać przy wykorzystaniu pętli 

for

, jednak element 

sterujący 

DataGrid

 udostępnia znacznie wygodniejszy mechanizm prezentacji danych. Do 

pobrania i wyświetlenia informacji o wszystkich podfolderach moŜna by uŜyć funkcji 
rekurencyjnej.  

Stwórzmy teraz nieco bardziej przydatny przykład. Stworzymy przeglądarkę plików, której będzie 
moŜna uŜyć do przeglądnięcia zawartości całego dysku twardego, podobnie jak Eksploratora 
Windows. Strona ta powinna dawać uŜytkownikom moŜliwość wyświetlania zawartości folderów i 
poruszania się po ich strukturze (podobnie jak Eksplorator Windows), jak równieŜ pozwalać na 
podanie nazwy wybranego folderu, co usprawni poruszanie się po zawartości dysku. Kod strony 
ASP.NET o powyŜszych moŜliwościach funkcjonalnych przedstawiony został na listingu 13.3. 

 

Listing 13.3. 

System poruszania się i prezentacji zawartości systemu plików — 

listing1303.aspx

 

1

 

<%@ Import Namespace="System.IO" %> 

2

 

<script language="VB" runat="server"> 

3

 

   private dir as DirectoryInfo 

4

 

   private f as FileInfo 

5

 

   private strDir as string 

6

 

    

7

 

   sub Page_Load(obj as object, e as eventargs) 

8

 

      if not Page.IsPostBack then 

9

 

         strDir = Request.Params("dir") 

10

 

       

11

 

         if strDir = "" then 

12

 

            strDir = "c:\" 

13

 

         end if 

14

 

       

background image

15

 

         tbDir.Text = strDir 

16

 

         dir = new DirectoryInfo(strDir) 

17

 

         ListFiles() 

18

 

      end if 

 

19

 

   end sub 

20

 

 

21

 

   sub tbDir_Handle(obj as object, e as EventArgs) 

22

 

      strDir = obj.Text 

23

 

      if Directory.Exists(strDir) then 

24

 

         dir = new DirectoryInfo(strDir) 

25

 

         ListFiles() 

26

 

      else 

27

 

         lblMessage.Text = "Bł

ę

dna nazwa folderu" 

28

 

      end if 

29

 

   end sub 

30

 

 

31

 

   sub ListFiles() 

32

 

      dim hl as HyperLink 

33

 

      dim d as DirectoryInfo 

34

 

      if not dir.Root.FullName = dir.FullName then 

35

 

         hl = new HyperLink 

36

 

         hl.Text = ".." 

37

 

         hl.NavigateURL = "listing1303.aspx?dir=" & _ 

38

 

            Server.URLEncode(dir.Parent.FullName) 

39

 

         Panel1.Controls.Add(hl) 

40

 

          

41

 

         Panel1.Controls.Add(new LiteralControl("<br>")) 

42

 

      end if 

43

 

       

44

 

      for each d in dir.GetDirectories 

45

 

         hl = new Hyperlink 

46

 

         hl.Text = d.Name 

47

 

         hl.NavigateURL = "listing1303.aspx?dir=" & _ 

48

 

            Server.URLEncode(d.FullName) 

49

 

         Panel1.Controls.Add(hl) 

50

 

          

51

 

         Panel1.Controls.Add(new LiteralControl("<br>")) 

52

 

      next 

53

 

       

54

 

      for each f in dir.GetFiles("*.*") 

55

 

         lblMessage.Text += f.Name & "<br>" 

56

 

      next 

57

 

   end sub 

58

 

</script> 

 

Analiza 

Zapisz powyŜszy kod w pliku o nazwie 

listing1303.aspx

. Za pierwszym razem gdy uŜytkownik 

wyświetli tę stronę w przeglądarce, zostanie wyświetlona zawartość folderu głównego (w tym 
przypadku 

C:\

). W wierszu 9. pobierana jest wartość parametru Ŝądania o nazwie 

dir

 — słuŜy 

ona do określenia folderu, którego zawartość naleŜy wyświetlić. 

Jeśli parametr 

dir

 nie został podany (co ma miejsce podczas pierwszego wyświetlenia strony), to 

wyświetlana jest zawartość folderu domyślnego — 

C:\

. W wierszu 16. tworzony jest nowy obiekt 

DirectoryInfo

 zawierający informacje dotyczące bieŜącego folderu, w wierszu 15., w polu 

tekstowym jest wyświetlana nazwa tego folderu (poprzez określenie wartości właściwości 

Text

 

pola tekstowego); a w wierszu 17. — wywoływana procedura 

ListFiles

 

Procedura 

ListFiles

, której kod rozpoczyna się w wierszu 31., pobiera po kolei wszystkie 

elementy kolekcji folderów bieŜącego obiektu 

DirectoryInfo

. Wcześniej jednak, w wierszu 34., 

procedura sprawdza czy znajdujemy się na głównym poziomie dysku. Jeśli nie, to konieczne 
będzie wyświetlenie połączenia "

..

", które umoŜliwi przejście do folderu nadrzędnego. W tym 

celu tworzony jest nowy obiekt 

HyperLink

, który wyświetla na stronie łańcuch znaków "

..

" i 

kojarzy z nim adres URL bieŜącej strony APS.NET z łańcuchem zapytania zawierającym ścieŜkę 
do folderu nadrzędnego. Gdy uŜytkownik kliknie to połączenie, wykonywana jest ta sama strona, 
lecz przekazany do niej w łańcuchu zapytania parametr 

dir

 będzie zawierać nową ścieŜkę dostępu 

— w tym przypadku ścieŜkę do folderu nadrzędnego. Procedura obsługi zdarzenia 

Page Load

 

wykorzysta tę ścieŜkę do stworzenia nowego obiektu 

DirectoryInfo

. W wierszu 41. tworzony 

background image

jest nowy obiekt 

LiteralControl

, który słuŜy do dodania znacznika 

<br>

 pod połączeniu do 

folderu nadrzędnego. 

Dla kaŜdego folderu wykonywana jest ta sama, jedna czynność — tworzony jest element sterujący 

Hyperlink

 odsyłający uŜytkownika z powrotem do tej samej strony ASP.NET. Element ten 

wyświetla na stronie krótką nazwę folderu (patrz wiersz 46.) i dodaje jego pełną nazwę do 
łańcucha zapytania (w wierszu 47.). Nasz przykładowa strona uŜywa tego parametru do 
wyświetlenia zawartości nowego folderu. W wierszu 51. ponownie jest tworzony obiekt 

LiteralControl

, który dodaje znacznik 

<br>

 po połączeniu. 

 

W wierszach do 54. do 56. pobierane są po kolei wszystkie nazwy plików przechowywanych w 
aktualnie przetwarzanym folderze. Nazwy te są następnie wyświetlane przy wykorzystaniu 
etykiety. Zanim przeanalizujemy ostatnią procedurę umieszczoną w naszej przykładowej stronie 
— 

tbDir_Handle

 — przyjrzymy się fragmentowi kodu strony definiującemu jej interfejs 

uŜytkownika. Został on przedstawiony na listingu 13.4. 

 

Listing 13.4. 

Kod definiujący interfejs uŜytkownika strony prezentującej zawartość systemu 

plików — 

listing1303.aspx

 

1

 

<html><body> 

2

 

   <form runat="server"> 

3

 

      <b>Foldery:</b>  

4

 

      <asp:Textbox id="tbDir" runat="server"  

5

 

         OnTextChanged="tbDir_Handle" 

6

 

         AutoPostBack=true /><p> 

7

 

      <asp:Panel id="Panel1" runat="server" 

8

 

         MaintainState="true" /> 

9

 

      <asp:label id="lblMessage" runat=server 

10

 

         maintainstate=false /> 

11

 

   </form> 

12

 

</body></html> 

 

Analiza 

Nasza przykładowa strona ASP.NET zawiera trzy elementy — element sterujący 

TextBox

 

wyświetlający ścieŜkę dostępu do bieŜącego folderu, 

Panel

 zawierający elementy sterujące 

HyperLink

 oraz etykietę (element sterujący 

Label

) słuŜący do wyświetlania nazw plików oraz 

wszelkich innych komunikatów tekstowych. Jeśli zawartość pola tekstowego ulegnie zmianie (co 
zapewne się stanie gdy uŜytkownik samemu poda nazwę folderu), zostanie wywołana procedura 

tbDir_Handle

 obsługująca zdarzenie 

TextChanged

Kod tej procedury został przedstawiony na listingu 13.3, w wierszach od 21. do 29. Pobiera ona 
tekst zapisany w polu tekstowym i wykorzystuje go do określenia nowego folderu. NaleŜy zwrócić 
uwagę na instrukcję 

if

 umieszczoną w wierszu 23. OtóŜ za kaŜdym razem gdy uŜytkownik ma 

moŜliwość własnoręcznego podania jakichkolwiek informacji, warto upewnić się, Ŝe są one 
poprawne. W tym przypadku wykorzystywana jest metoda 

DirectoryExists

, która sprawdza 

czy podana ścieŜka wskazuje istniejący folder. Jeśli ścieŜka nie jest prawidłowa, to zostanie 
wyświetlony stosowny komunikat. Podobne testy są niezwykle istotne, szczególnie w aplikacjach 
tego typu.  

W końcu, jeśli podana ścieŜka jest poprawna, ponownie wywoływana jest procedura 

ListFiles

która wyświetla zawartość nowego folderu. Wyniki wykonania tej strony zostały przedstawione na 
rysunku 13.6. 

 

background image

 

Rysunek 13.6. 

Przykładowy listing zawartości folderu wykonany przy uŜyciu naszej 

przykładowej aplikacji 

 

Nie wspominałem jeszcze o dwóch zagadnieniach związanych z tą aplikacją. Pierwszym z nich 
jest wykorzystanie metody 

Server.URLEncode

. OtóŜ za kaŜdym razem gdy tworzony jest nowy 

obiekt 

Hyperlink

 i określany łańcuch zapytania, wywoływana jest takŜe metoda 

Server.URLEncode

. Zapewnia ona, Ŝe wszelkie znaki specjalne zostaną odpowiednio 

zakodowane do postaci łańcuchów znaków, które nie spowodują powstania nieprawidłowego 
adresu URL. Na przykład, gdyby ścieŜka dostępu do pliku miała postać 

c:\Program Files\temp.txt

to odstęp pomiędzy słowami „Program” i „Files” mógłby spowodować wystąpienie błędów. Po 
wywołaniu metody Server.URLEncode ścieŜka ta zostanie zamieniona do następującej postaci: 

c%3a%5cprogram+files%5ctemp.txt 

Wszystkie znaki, które nie mogą występować w adresie URL znakami, które protokół HTTP 
akceptuje i traktuje jako zamienniki. 

Kolejnym zagadnieniem o którym jeszcze nie pisałem, są róŜne sposoby wywoływania naszej 
przykładowej strony ASP.NET. W procedurze 

Page_Load

 sprawdzamy czy strona została 

wyświetlona po raz pierwszy. Jeśli nie, będzie to oznaczało, iŜ uŜytkownik zmienił bieŜący folder 
poprzez kliknięcie któregoś z elementów sterujących 

Hyperlink

 (nie powodują one przesłania 

formularza, a jedynie przekierowanie do wskazanej strony). W takim przypadku naleŜy wykonać 
procedurę 

Page_Load

 i wyświetlić zawartość wskazanego folderu. Jeśli okaŜe się, Ŝe strona nie 

została wyświetlona po pierwszy lecz w efekcie Ŝądania przesłanego z tej samej strony, to do 
wyświetlenia zawartości bieŜącego folderu naleŜy uŜyć procedury 

tbDir_Handle

. Sprawdzenie 

tego warunku jest niezwykle istotne, gdyŜ bez niego zawartość folderu mogłaby zostać 
wyświetlona dwukrotnie. 

background image

Otwieranie plików 

ASP.NET udostępnia kilka sposobów otwierania plików, które moŜna wykorzystywać w 
zaleŜności od zaistniałych okoliczności. Zgodnie z informacjami podanymi wcześniej, ASP.NET 
umoŜliwia otwieranie plików w celu odczytu zarówno danych binarnych jak i tekstowych (w 
przypadku ASP.NET zapisanych w kodzie Unicode). Tryb odczytu danych binarnych pozwala na 
bezpośrednie odczytywanie poszczególnych bitów tworzących plik. Unicode jest pewnym 
schematem umoŜliwiającym przekształcenie tych bitów w coś co my — ludzie — moŜemy łatwo 
odczytać; na przykład w cyfry i litery. PoniewaŜ dostęp do danych binarnych nie będzie nam 
potrzebny, skoncentrujemy się na operowaniu na danych tekstowych. 

U

Ŝ

ycie obiektów klasy FileInfo 

Jednym ze sposobów otwierania plików jest uŜycie obiektów 

FileInfo

1

. Po stworzeniu kopii 

takiego obiektu i skojarzeniu go z plikiem o podanej nazwie, moŜna wykorzystać kilka metod 
słuŜących do otwierania plików. Wybór konkretnej metody będzie zaleŜał od tego, co chcemy 
zrobić z zawartością pliku. Wszystkie dostępne metody zostały przedstawione w tabeli 13.2. 

 

Tabela 13.2. 

Metody 

Open

 klasy 

FileInfo

 

Metoda 

Opis 

Open 

Otwiera plik przy wykorzystaniu podanych uprawnień i zwraca obiekt 

Stream

OpenRead() 

Zwraca strumień do pliku umoŜliwiający wyłącznie odczyt jego zawartości. 

OpenText() 

Zwraca obiekt 

StreamReader

 dla danego pliku. 

OpenWrite() 

Zwraca obiekt 

Stream

 umoŜliwiający zarówno odczyt jak i zapis informacji w 

pliku. 

 

Metody te trzeba omówić nieco szerzej. W pierwszej kolejności przyjrzyjmy się typom dostępnych 
uprawnień.  

W wywołaniu metody 

Open

 moŜna podać trzy argumenty — 

FileMode

FileAccess

 oraz 

FileShare

 (w podanej kolejności). Pierwszy z nich — 

FileMode

 — informuje system 

operacyjny w jaki sposób naleŜy otworzyć plik, na przykład czy zawartość istniejącego pliku ma 
być usunięta, czy teŜ naleŜy dopisać do nie nowe informacje zapisywane w pliku. Dostępne tryby 
otwierania plików zostały przedstawione w tabeli 13.3. 

 

Tabela 13.3. 

Dostępne wartości argumentu FileMode 

Tryb 

Opis 

Append 

Otwiera plik jeśli istnieje i przechodzi na jego koniec. Jeśli plik nie istnieje, to 
tworzony jest nowy plik. Ten tryb otwierania plików moŜe zostać wykorzystany 
tylko w przypadku otwierania plików z uprawnieniem do zapisu (

Write

 — za 

chwilę go opiszę). 

Create 

Tworzy nowy plik bądź „nadpisuje” istniejący plik (usuwa jego aktualną 
zawartość). 

CreateNew 

Tworzy nowy plik. 

Open 

Otwiera istniejący plik. 

OpenOrCreate 

Otwiera plik jeśli istnieje, a w przeciwnym razie tworzy nowy. 

                                                           

1

 Opisywane w tej części rozdziału metody 

Open

 są takŜe dostępne w klasie 

File

background image

Truncate 

Otwiera istniejący plik, a następnie skraca go do długości 0 bajtów, co w 
rezultacie powoduje usunięcie całej jego aktualnej zawartości. 

 

Argument 

FileAccess

 określa przywileje dostępu do pliku. Dostępne wartości tego atrybutu to: 

Read

ReadWrite

 oraz 

Write

; odpowiednio otwierają plik w trybie do odczytu, odczytu i zapisu 

bądź tylko do zapisu. 

Ostatni argument — 

FileShare

 — określa co się stanie jeśli dwa procesy jednocześnie spróbują 

uzyskać dostęp do tego samego pliku; na przykład, jeśli dwie osoby wyświetlą stronę WWW i w 
tej samej chwili spróbują zmienić zawartość pliku. Wartość tego argumentu ma wpływ na proces, 
który spróbuje uzyskać dostęp do pliku jako drugi. Wartości te są takie same jak wartości 
argumentu 

FileAccess

, z jedną róŜnicą — dostępny jest dodatkowa wartość 

None

, która 

informuje, Ŝe w danej chwili plik moŜe być wykorzystywany tylko przez jeden proces. 

Być moŜe zauwaŜyłeś, Ŝe wszystkie metody 

Open

 klasy 

FileInfo

 za wyjątkiem metody 

OpenText

, zwracają obiekty 

Stream

 dające wyłącznie moŜliwość odczytu danych binarnych. 

Oczywiście do naszych celów nie jest to dobre. W dalszej części rozdziału, podczas prezentacji 
zagadnień związanych z odczytywaniem zawartości plików, pokaŜę jak ominąć ten problem. 

Przedstawiony poniŜej fragment kodu pokazuje w jaki sposób moŜna otworzyć plik przy 
wykorzystaniu obiektu 

FileInfo

 
'tworzymy obiekty FileInfo i StreamRader 
dim objFile as new FileInfo(Server.MapPath("log.txt")) 
dim objReader as StreamReader 
 
'otwieramy plik 
objReader = objFile.OpenText() 
 
'inne czynno

ś

ci 

 
'zamykamy strumie

ń

 

objReader.close 
 

MoŜna takŜe wykorzystać metodę 

Open

dim objFile as new FileInfo(Server.MapPath("log.txt")) 
dim objStream as Stream 
objStream = objFile.Open( FileMode.OpenOrCreate, FileAccess.Read ) 
 

U

Ŝ

ycie obiektów klasy FileStream 

Klasa 

FileStream

 pozwala na tworzenie strumieni umoŜliwiających dostęp do plików. Jedną z 

zalet wykorzystania obiektów 

FileStream

 jest to, iŜ nie stwarzają one konieczności 

wcześniejszego uŜycia obiektów 

FileInfo

. Niemniej jednak naleŜy się upewnić, iŜ plik do 

którego chcemy uzyskać dostęp naprawdę istnieje. Nie było to konieczne w przypadku 
posługiwania się obiektami 

FileInfo

, gdyŜ sam fakt pomyślnego utworzenia takiego obiektu 

oznaczał istnienie pliku. PoniŜszy fragment kodu pokazuje w jaki sposób moŜna otworzyć plik 
przy wykorzystaniu obiektu 

FileStream

dim objF as new FileStream(Server.MapPath("log.txt"), _ 
  FileMode.OpenOrCreate) 
 

PowyŜsze wywołanie otwiera plik w trybie 

OpenOrCreate

. Konstruktor klasy 

FileStream

 

wykorzystuje te same argumenty co metoda 

Open

 klasy 

FileInfo

, z tym iŜ pierwszym 

argumentem wywołania musi być łańcuch znaków określający nazwę otwieranego pliku. 

Klasa 

FileStream

 udostępnia takŜe metodę 

Seek

, która umoŜliwia przejście do dowolnego 

miejsca strumienia (na przykład, na jego początek lub koniec). Składnia wywołania tej metody ma 
następującą postać: 

Seek(przesuni

ę

ciepunktOdniesienia

 

Argument 

przesuni

ę

cie

 określa odległość na jaką naleŜy przejść względem podanego 

punktuOdniesienia

. Argumentem 

punktOdniesienia

 moŜe być jedną z wartości typu 

background image

wyliczeniowego 

SeekOrigin

SeekOrigin.Begin

 (oznacza, Ŝe przesunięcie będzie liczone od 

początku pliku), 

SeekOrigin.Current

 (oznacza, Ŝe przesunięcie będzie liczone względem 

bieŜącego połoŜenia w pliku) oraz 

SeekOrigin.End

 (oznacza, Ŝe przesunięcie będzie liczone 

względem końca pliku). Na przykład, poniŜszy fragment kodu powoduje przejście na początek, a 
następnie na koniec pliku: 

'przechodzimy na pocz

ą

tek pliku 

objF.Seek( 0, SeekOrigin.Begin ) 
'przechodzimy na koniec pliku 
objF.Seek( 0, SeekOrigin.End ) 
 

Odczyt plików 

Teraz, kiedy juŜ wiesz jak naleŜy otwierać pliki, moŜemy zająć się odczytywaniem ich zawartości. 
W ASP.NET czynność ta jest wykonywana głównie przy wykorzystaniu obiektów klasy 

StreamReader

. Zgodnie z tym co zostało podane wcześniej, obiekty tej klasy konwertują dane 

binarne do postaci tekstowej, dzięki czemu otrzymujemy znaki oraz łańcuchy znaków, którymi 
naleŜy posługiwać się na stronach ASP.NET. Stworzenie obiektu klasy 

StreamReader

 jest 

bardzo proste: 

dim objReader as new StreamReader(obiekt
 

Argumentem 

obiekt

 moŜe być obiekt 

Stream

 (na przykład obiekt 

FileStream

 utworzony w 

poprzedniej części rozdziału) bądź ścieŜka dostępu do konkretnego pliku. Stwórzmy teraz prosty 
plik, którego będziemy uŜywali w dalszych przykładach; będzie on nosił nazwę 

log.txt

 i naleŜy 

zapisać go w folderze 

/aspnetdlakazdego/rozdzial13

. PoniŜej przedstawiłem zawartość tego pliku: 

Zwinne lisy 
przeskoczyły nad 
leniwym  
br

ą

zowym psem 

 

Klasa 

StreamReader

 udostępnia kilka metod słuŜących do odczytywania znaków z pliku. 

Pierwsza z nich — 

Read

 — odczytuje ze strumienia pojedynczy znak, zwraca go w formie liczby 

całkowitej i przechodzi do kolejnego znaku. Oto przykład jej wykorzystania: 

dim f as new FileInfo(Server.MapPath("log.txt")) 
dim objReader as StreamReader  
objReader = f.OpenText 
Response.Write(objReader.Read & "<br>") 
objReader.Close 
 

Wykonanie powyŜszego fragmentu kodu spowoduje wyświetlenie na stronie liczby 90, która jest 
wartością litery „Z” w kodzie ASCII. Kolejne wywołanie metody 

Read

 spowodowałoby 

wyświetlenie liczby 119, odpowiadającej w kodzie ASCII literze „w”. I tak dalej. Jednak liczby te 
nie są dla nas przydatne, a zatem naleŜy przekształcić je do postaci znaków zapisanych w kodzie 
Unicode. SłuŜy do tego metoda 

Chr

 klasy 

Strings

Response.Write(Strings.Chr(objReader.Read) & "<br>") 

 

Pierwsze wykonanie powyŜszego fragmentu kodu po otworzeniu strumienia powinno zwrócić 
literę „Z”, drugie „w” i tak dalej. 

Jednak odczytywanie pojedynczych znaków moŜe być nieco męczące, dlatego teŜ klasa 

StreamReader

 udostępnia dwie inne metody, które zwracają całe łańcuchy znaków. Metodami 

tymi są: 

ReadLine

 (która odczytuje znaki aŜ do końca wiersza) oraz 

ReadToEnd

 (która odczytuje 

całą pozostałą zawartość strumienia). PoniŜej przedstawiony został przykład uŜycia metody 

ReadToEnd

dim objReader as new StreamReader(Server.MapPath("log.txt")) 
Response.Write(objReader.ReadToEnd) 
objReader.Close 
 

Wykonanie  powyŜszego fragmentu kodu spowoduje wyświetlenie łańcucha znaków: 

Zwinne lisy przeskoczyły nad leniwym br

ą

zowym psem 

background image

 

A co się stało ze znakami końca wiersza? Jeśli przejrzysz kod HTML wygenerowanej strony, to 
zauwaŜysz, Ŝe znaki te zostały w nim umieszczone. Niestety język HTML nie interpretuje znaków 
końca wiersza jako znaczników przełamania wiersza (

<br>

). Znaczniki te moŜna umieścić w 

odpowiednich miejscach wykorzystując metodę 

ReadLine

Response.Write(objReader.ReadLine & "<br>") 
 

Metoda ta odczytuje jednak tylko jeden wiersz, a zatem, aby odczytać całą zawartość pliku 
konieczne będzie wykorzystanie pętli. Gdy dotrzesz do końca pliku, to próba odczytania kolejnych 
znaków przy uŜyciu metod 

Read

 lub 

ReadLine

 spowoduje zgłoszenie błędu. Na szczęście, klasa 

StreamReader

 udostępnia metodę 

Peek

, która umoŜliwia uniknięcie tej przykrej sytuacji. 

Metoda 

Peek

 odczytuje kolejny znak ze strumienia, lecz w rzeczywistości go nie zwraca — 

innymi słowy pozwala „podejrzeć” ten znak. Jeśli tym znakiem będzie koniec strumienia, to 
metoda zwraca wartość 

-1

. Posługując się tą metodą moŜna odczytać całą zawartość strumienia 

bez jakichkolwiek problemów: 

dim objReader as new StreamReader(Server.MapPath("log.txt")) 
while objReader.Peek() > -1 
 Response.Write(objReader.ReadLine & "<br>") 
end while 
objReader.Close 
 

Wyniki wykonania powyŜszego fragmentu kodu przedstawione zostały na rysunku 13.7. 

 

 

Rysunek 13.7. 

Odczytywanie zawartości strumienia przy uŜyciu metody 

ReadLine

 

 

Ostrze

Ŝ

enie 

Poniewa

Ŝ

  metoda  Peek  nie  odczytuje  znaku  ze  strumienia,  a  zatem  nie  zmienia  tak

Ŝ

bie

Ŝą

cego  poło

Ŝ

enia  w  strumieniu,  pami

ę

tanego  przez  obiekt 

StreamReader

.  Dlatego  te

Ŝ

 

konieczne  jest  wykorzystanie  metod  klasy 

StreamReader

  w  celu  przesuni

ę

cia  bie

Ŝą

cego 

poło

Ŝ

enia w strumieniu, gdy

Ŝ

 inaczej łatwo mo

Ŝ

na stworzy

ć

 niesko

ń

czon

ą

 p

ę

tl

ę

, której przykład 

został przedstawiony na poni

Ŝ

szym przykładzie: 

while objReader.Peek () > -1 
  Response.Write("<br>") 
end while 

background image

Uruchomienie  tego  fragmentu  kodu  spowoduje  prób

ę

  wykonania  niesko

ń

czonej  p

ę

tli,  która 

powstaje gdy

Ŝ

 bie

Ŝą

ce poło

Ŝ

enie w strumieniu nigdy nie jest modyfikowane. 

 

Do zwrócenia określonej ilości znaków ze strumienia moŜna takŜe uŜyć metody 

Read

. W tym 

przypadku składnia wywołania tej metody ma następującą postać: 

objReader.Read(char()pocz

ą

tekilo

ść

 

Ta wersja metody 

Read

 odczytuje ze strumienia podaną 

ilo

ść

 znaków, rozpoczynając w miejscu 

określonym przy uŜyciu argumentu 

pocz

ą

tek

. Odczytane znaki zostają zapisane w tablicy typu 

Char

 przekazanej jako pierwszy argument wywołania metody. Oto przykład: 

dim objReader as new StreamReader(Server.MapPath("log.txt")) 
dim arrString(11) as Char 
dim i as Byte 
 
objReader.Read(arrString, 0, 11) 
for i = 0 to Ubound(arrString) - 1 
  Response.Write(arrString(i)) 
next 
 
objReader.Close 
 

W wierszu 2. jest tworzona tablica typu 

Char

, zapisywana w zmiennej 

arrString

. W wierszu 5. 

jest wywoływana metoda 

Read

, która odczytuje ze strumienia 11 znaków, rozpoczynając od jego 

początku. Znaki tez zostają zapisane w tablicy 

arrString

. Wykonanie powyŜszego fragmentu 

kodu spowoduje wyświetlenie łańcucha znaków  

Zwinne lisy 
 

To dziesięć znaków i jeden odstęp (litera 

y

 jest ostatnim znakiem). 

Wyobraź sobie, Ŝe w celach demonstracyjnych chcielibyśmy wyświetlić kod źródłowy jednej z 
naszych stron ASP.NET, tak aby uŜytkownicy witryny mogli go przeanalizować i, na przykład, 
poznać jedną z omawianych tu metod odczytu plików. Jednak jeśli uŜytkownik spróbuje odwołać 
się do strony ASP.NET przy uŜyciu przeglądarki WWW, to uzyska wyłącznie kod HTML — 
wszystkie instrukcje ASP.NET zostaną bowiem przetworzone i usunięte. A zatem to my będziemy 
musieli wyświetlić zawartość strony zanim zostanie ona przetworzona. MoŜna to zrobić przy 
wykorzystaniu klas udostępnianych w przestrzeni nazw 

System.IO

. Przykład takiej aplikacji 

przedstawiony został na listingu 13.5. 

 

Listing 13.5. 

Wyświetlanie kodu źródłowego stron ASP.NET w przeglądarce. 

1

 

<%@ Import Namespace="System.IO" %> 

2

 

<script language="VB" runat="server"> 

3

 

   sub Page_Load(obj as object, e as eventargs) 

4

 

      dim fs as new FileStream(Server.MapPath _ 

5

 

         ("listing1305.aspx"), FileMode.Open, FileAccess.Read) 

6

 

      dim objReader as new StreamReader(fs) 

7

 

       

8

 

      lblMessage.Text = "<pre>" 

9

 

      while objReader.Peek() > -1 

10

 

         lblMessage.Text += Server.HTMLEncode _ 

11

 

            (objReader.ReadLine) & "<br>" 

12

 

      end while 

13

 

      objReader.Close 

14

 

      fs.close 

15

 

      lblMessage.Text += "</pre>" 

16

 

       

17

 

   end sub 

18

 

</script> 

19

 

 

20

 

<html><body> 

21

 

   <form runat="server"> 

22

 

       <asp:label id="lblMessage" runat=server /> 

23

 

   </form> 

24

 

</body></html> 

 

background image

Analiza 

W procedurze 

Page_Load

 tworzony jest nowy obiekt 

FileStream

, który posłuŜy nam do 

odczytania zawartości wybranego pliku. W wierszu 7. tworzony jest obiekt 

StreamReader

, który 

umoŜliwia dostęp do zawartości pliku. UŜycie znacznika 

<pre>

 sprawia, Ŝe formatowanie na 

wynikowej stronie WWW będzie przypominało oryginalny sposób formatowania wyświetlanego 
kodu. W dalszej części procedury wykonywana jest pętla 

while

, która przy wykorzystaniu metod 

Peek

 oraz 

ReadLine

 wyświetla poszczególne wiersze pliku. Przy wyświetlaniu kodu 

odczytywanego z pliku uŜywana jest takŜe metoda 

Server.HTMLEncode

, która zapewnia, Ŝe 

znaczniki HTML nie będą interpretowane. Na końcu procedury są zamykane obiekty 

StreamReader

 oraz 

FileStream

 oraz generowany zamykający znacznik 

</pre>

. Wyniki 

wykonania powyŜszej strony ASP.NET zostały przedstawione na rysunku 13.8. 

 

 

Rysunek 13.8. 

Wyświetlanie kodu źródłowego strony ASP.NET w przeglądarce 

 

Zapis plików 

Zapisywanie danych do strumieni umoŜliwiają obiekty klasy 

StreamWriter

. Składnia instrukcji 

słuŜącej do utworzenia takiego obiektu jest bardzo prosta. Obiekty tej klasy, podobnie jak obiekty 

StreamReader

 moŜna utworzyć na postawie obiektu 

Stream

 bądź ścieŜki dostępu określającej 

połoŜenie pliku: 

dim objWriter as new StreamWriter(FileStreamLub

Ś

cie

Ŝ

kadopisa

ć

 

Argument 

dopisa

ć

 jest wartością logiczną (typu 

Boolean

) określającą czy nowe informacje 

powinny zostać dopisane do istniejącej zawartości pliku. Jeśli argument ten przyjmie wartość 

false

, to istniejąca zawartość pliku zostanie usunięta. Jeśli wskazany plik nie istnieje, zostanie on 

utworzony. Jeśli argument 

dopisa

ć

 będzie miał wartość 

true

, to wszystkie informacje 

zapisywane w pliku zostaną dodane na jego końcu, za istniejącą zawartością. 

background image

Klasa 

StreamWriter

 udostępnia dwie metody słuŜące do zapisywania danych — 

Write

 oraz 

WriteLine

. Oto przykład ich wykorzystania: 

dim objWriter as new StreamWriter _ 
        (Server.MapPath("log.txt"), true ) 
 
objWriter.WriteLine("Ale pies zupełnie") 
objWriter.Write("si

ę

 tym nie przej

ą

ł") 

 
objWriter.Close 
 

W wierszu 1. tworzony jest obiekt 

StreamWriter

 skojarzony z plikiem 

log.txt

, a jednocześnie 

informujemy, Ŝe nowe informacje mają być dopisywane do istniejącej zawartości pliku. W 
wierszach 4. i 5. zostają wywołane dwie metody słuŜące do zapisu danych w pliku, po czym obiekt 
pisarza (

StreamWriter

) zostaje zamknięty. Po wykonaniu powyŜszego fragmentu kodu, 

zawartość pliku 

log.txt

 będzie miała następującą postać: 

Zwinne lisy 
przeskoczyły nad 
leniwym  
br

ą

zowym psemAle pies zupełnie 

si

ę

 tym nie przej

ą

ł 

 

Jak widać, po tekście zapisanym przy uŜyciu metody 

WriteLine

 został umieszczony znak 

nowego wiersza. Jednak oryginalna zawartość pliku oraz tekst dodany do niego przez nasz 
przykładowy program, nie są w Ŝaden sposób oddzielone. Aby zapisać w pliku znak nowego 
wiersza, wystarczy wywołać metodę 

WriteLine

 nie podając w jej wywołaniu Ŝadnych 

argumentów: 

objWriter.WriteLine() 
 

Obiekty 

StreamWriter

 wykorzystują bufor wyjściowy. Przypominasz sobie zapewne 

zagadnienia związane z buforowanie generowanych stron, opisane w rozdziale 4., pt.: „Stosowanie 
obiektów ASP.NET w językach C# i VB.NET”. Domyślnie, obiekty 

StreamWriter

 umieszczają 

dane w buforze przed przekazaniem ich do strumienia. Jeśli chcesz, aby dane były przesyłane do 
strumienia po kaŜdym wywołaniu metody 

Write

 lub 

WriteLine

, wystarczy przypisać 

właściwości 

AutoFlush

 obiektu 

StreamWriter

 wartość 

true

MoŜna takŜe ręcznie przekazać zawartość bufora do strumienia, wywołują metodę 

Flush

Przypisanie właściwości 

AutoFlush

 wartości 

true

 moŜe jednak sprawić, iŜ efektywność 

działania aplikacji będzie nieco lepsza. Automatyczne opróŜnienie bufora (poprzez przypisanie 
właściwości 

AutoFlush

 wartości 

true

) naleŜy stosować, w sytuacji gdy uŜytkownicy oczekują 

natychmiastowych wyników. Na przykład, podczas zapisywania w pliku duŜej ilości danych, w 
sytuacji gdy chcesz, aby uŜytkownicy mogli zobaczyć wprowadzane modyfikacje jeszcze przed 
zakończeniem przetwarzania pliku. 

Inne operacje na plikach i folderach 

Zarówno klasa 

File

 jak i 

Directory

 udostępniają metody słuŜące do kopiowania, tworzenia, 

przenoszenia oraz usuwania plików i folderów. Ich uŜycie jest bardzo proste i nie wymaga 
większego komentarza. Metody te przedstawiłem w tabeli 13.4; dotyczą one zarówno klasy 

File

 

jak i 

Directory

, chyba Ŝe jawnie napisałem, Ŝe tak nie jest. 

 

Tabela 13.4. 

RóŜne metody klas 

File

 i 

Directory

 

Metoda 

Opis 

Directory.CreateDirectories 

Tworzy wszystkie foldery określone w podanej ścieŜce. 

Directory.CreateDirectory 

Tworzy folder o określonej ścieŜce. Jeśli w jakimkolwiek 
miejscu ścieŜki zostanie uŜyty nieistniejący folder, to 
ASP.NET zgłosi błąd. 

background image

Directory.Delete 

Usuwa folder. Drugi argument wywołania tej metody — 

rekurencyjnie

 — jest wartością logiczną, określającą 

czy naleŜy takŜe usunąć wszystkie podfoldery oraz pliki. 

File.Copy 

Kopiuje istniejący lub nowy plik. Trzeci argument 
wywołania tej metody — 

nadpisa

ć

 — to wartość 

logiczna określająca czy istniejący plik powinien zostać 
nadpisany. 

File.Create 

Tworzy plik o określonej ścieŜce dostępu. 

File.CreateText 

Tworzy nowy obiekt 

StreamWriter

 umoŜliwiający zapis 

danych w nowym pliku. 

File.Delete 

Usuwa plik. 

File.ChangeExtension 

Zmienia rozszerzenie pliku określonego przy uŜyciu 
podanej ścieŜki. Aby usunąć rozszerzenie pliku, naleŜy 
przypisać argumentowi 

rozszerzenie

 wartość 

nothing

Nie zapomnij zapisać kropki przez nowym rozszerzeniem. 
Ta statyczna metoda zwraca ścieŜkę dostępu do pliku z 
nowym rozszerzeniem. 

File.GetExtension 

Ta statyczna metoda zwraca rozszerzenie pliku. 

File.HasExtension 

Ta statyczna metoda zwraca wartość 

true

 jeśli podany 

plik ma rozszerzenie. 

Move 

Przenosi wskazany plik lub folder określony jako 

stara

Ś

cie

Ŝ

ka

 w miejsce określone jako 

nowa

Ś

cie

Ŝ

ka

 

Aby zmienić nazwę pliku lub folderu moŜna go przenieść (przy uŜyciu metody 

Move

) lub 

skopiować (metodą 

Copy

) a następnie usunąć (przy uŜyciu metody 

Delete

). 

 

Podsumowanie informacji o plikach i folderach 

Ze względu na fakt, iŜ ASP.NET udostępnia tak wiele róŜnych klas umoŜliwiających operowanie 
na systemie plików, wybór której z nich naleŜy uŜyć moŜe przysporzyć wielu problemów. W 
tabeli 13.5. przedstawiłem dostępne klasy oraz podałem informacje o ich przeznaczeniu. 

 

Tabela 13.5. 

Klasy i typy wyliczeniowe zdefiniowane w przestrzeni nazw System.IO 

Klasa 

Kiedy naleŜy uŜywać obiektów tej klasy 

BinaryReader

 oraz 

BinaryWriter

 

SłuŜy do odczytywania i zapisywania informacji binarnych w 
strumieniach (na przykład dat oraz obiektów). 

Directory

 

Pozwala na tworzenie, usuwanie oraz wykonywanie innych operacji 
na folderach. 

File

 

Pozwala na tworzenie, usuwanie oraz wykonywanie innych operacji 
na plikach. 

FileInfo

 oraz 

DirectoryInfo

 

Te klasy pozwalają na przeglądanie oraz określanie właściwości 
plików i folderów. 

FileAttributes

 oraz 

DirectoryAttributes

 

Obiekty tych klas słuŜą do określania atrybutów plików i folderów. 

FileMode

FileAccess

 

Typy wyliczeniowe określające uprawnienia i tryby otwierania 
plików. 

background image

oraz 

FileShare

 

FileStream

 

Ta klasa zapewnia dostęp do pliku wraz z moŜliwością 
przechodzenia w jego dowolne miejsce. 

MemoryStream

 

Klasa ta zapewnia dostęp do strumieni umoŜliwiających zapis i 
odczyt danych nie z plików lecz pamięci komputera. 

SeekOrigin

 

Typ wyliczeniowy, którego wartości są uŜywane w wywołaniach 
metody 

FileStream.Seek

StreamReader

 oraz 

StreamWriter

 

Klasy te pozwalają na odczyt i zapis odpowiednio zakodowanych 
znaków w strumieniach bajtowych. 

StringReader

 oraz 

StringWriter

 

Klasy te pozwalają na odczyt i zapis danych w łańcuchach znaków. 
Ich moŜliwości funkcjonalne odpowiadają moŜliwościom klas 

StreamReader

 oraz 

StreamWriter

Składowanie izolowane 

Posługując się metodami przedstawionymi we wcześniejszej części rozdziału moŜna zapisywać 
dane w pliku o unikalnej ścieŜce dostępu, na przykład: 

c:\inetpub\wwwroot\aspnetdlakazdego\rozdzial13\log.txt

. To bardzo potęŜna i uŜyteczna metoda 

przechowywania informacji; ma jednak jedną wadę. 

Po pierwsze, dla kaŜdego pliku konieczna jest znajomość lub stworzenie unikalnej ścieŜki dostępu. 
Oczywiście, w przypadkach przedstawionych w tym rozdziale, nie stanowi to większego 
problemu; spróbuj jednak wyobrazić sobie aplikację która musi działać na róŜnych serwerach, z 
których kaŜdy ma własną, unikalną strukturę systemu plików. Zarządzanie tymi wszystkimi 
plikami przechowywanymi w róŜnych miejscach moŜe być prawdziwym utrapieniem.  

Po drugie, z tworzonych w taki sposób plików mogą korzystać takŜe inni uŜytkownicy oraz 
aplikacje, które mogą uzyskać dostęp do lokalnego systemu plików (czyli niemal kaŜdy — od 
osoby odwiedzającej strony WWW poczynając, a na uŜytkowniku lokalnego komputera kończąc). 
To doskonała moŜliwość w przypadku plików zawierających, na przykład, informacje dotyczące 
licznika odwiedzin, do których powinni mieć dostęp wszyscy korzystający z aplikacji. Co jednak 
zrobić w sytuacji, gdy chcesz wykorzystać pliki do przechowywania prywatnych informacji o 
kaŜdym z uŜytkowników? W takim przypadku trudno byłoby określić do kogo naleŜą 
poszczególne informacje. 

Wszystkie te problemy moŜna jednak rozwiązać dzięki wykorzystaniu mechanizmu składowania 
izolowanego dostępnego w ASP.NET. Mechanizm ten, pod pewnymi względami, przypomina 
cookies, gdyŜ kojarzy dane z uŜytkownikami i izoluje je. KaŜdy uŜytkownik otrzymuje swój 
własny izolowany obszar składowania. JuŜ nigdy nie trzeba będzie przejmować się określaniem 
unikalnych ścieŜek dostępu do plików. Mechanizm składowania izolowanego umoŜliwia 
zapisywanie danych w obszarach, które fizycznie mogą być przechowywane w dowolnym 
miejscu, nawet na lokalnym komputerze uŜytkownika (zupełnie jak cookies).  

Aby wykorzystać mechanizm składowania izolowanego, naleŜy poznać kilka nowych zagadnień. 
Potem jednak, sposoby działania tego mechanizmu będą przypominać standardowe metody 
uzyskiwania dostępu do plików. 

Tworzenie izolowanych obszarów składowania 

W przypadku posługiwania się mechanizmem składowania izolowanego wykorzystywane są 
obiekty dwóch klas — 

IsolatedStorageFile

 oraz 

IsolatedStorageFileStream

Przypominają one obiekty 

File

 oraz 

FileStream

 przedstawione w poprzedniej części rozdziału. 

W rzeczywistości klasa 

IsolatedStorageFileStream

 udostępnia te same metody co klasa 

FileStream

background image

W odróŜnieniu od obiektów 

File

, obiekty 

IsolatedStorageFile

 nie reprezentują plików lecz 

raczej obszary umoŜliwiające przechowywanie danych. Pliki przechowywane w tych obszarach są 
reprezentowane przez obiekty klasy 

IsolatedStorageFileStream

. Z początku róŜnice te 

mogą być nieco mylące, a zatem naleŜy dobrze zrozumieć przeznaczenie obu tych klas. 

Przeanalizujmy listing 13.6, który pokazuje w jaki sposób moŜna stworzyć plik w izolowanym 
obszarze składowania 

 

Listing 13.6. 

Tworzenie pliku w izolowanym obszarze składowania 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.IO" %> 

3

 

<%@ Import Namespace="System.IO.IsolatedStorage" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   sub Page_Load(obj as object, e as eventargs) 

7

 

      dim stream as IsolatedStorageFileStream 

8

 

      dim writer as StreamWriter 

9

 

      dim data as string = "niebieski" 

10

 

 

11

 

      stream = new IsolatedStorageFileStream("colors.txt", _ 

12

 

         FileMode.OpenOrCreate) 

13

 

      writer = new StreamWriter(stream) 

14

 

      writer.WriteLine(data) 

15

 

      writer.Close() 

16

 

   end sub 

17

 

</script> 

18

 

 

19

 

<html><body> 

20

 

</body></html> 

 

 

Analiza 

Zwróć uwagę, na wykorzystanie nowej przestrzeni nazw — 

System.IO.IsolatedStorage

 — 

importowanej w 3. wierszu. Nie zapomnij zaimportować jej takŜe we własnych stronach 
ASP.NET. W wierszach od 7. do 9. są deklarowane uŜywane zmienne, w tym takŜe nowy obiekt 
klasy 

IsolatedStorageFileStream

. Deklarowany w wierszu 8. obiekt 

StreamWriter

powinien juŜ wyglądać znajomo.  

Kolejny fragment kodu takŜe nie powinien zawierać Ŝadnych niespodzianek — jedyną 
wprowadzoną w nim nowością, jest uŜycie obiektu 

IsolatedStorageFileStream

. Składania 

instrukcji słuŜącej do stworzenia nowej kopii tego obiektu jest taka sama jak w przypadku 
tworzenia obiektów 

FileStream

. W wierszach 13. i 14. wykonujemy znane juŜ czynności 

posługując się przy tym obiektem 

StreamWriter

; a w wierszu 15. zamykamy go, co powoduje 

takŜe zamknięcie strumienia 

IsolatedStorageFileStream

. I to by było wszystko.  

Przedstawiony powyŜej przykład tworzy plik o nazwie 

colors.txt

 i zapisuje go w izolowanym 

obszarze składowania naleŜącym do bieŜącego uŜytkownika. Gdyby inny uŜytkownik spróbował 
uzyskać dostęp do tego pliku, nie było by to moŜliwe; podobnie jak nie jest moŜliwe uzyskanie 
dostępu do cookies innego uŜytkownika. Konkretne miejsce, w którym mechanizm składowania 
izolowanego przechowuje pliki, zaleŜy od uŜywanego systemu operacyjnego. Informacje ta ten 
temat zostały przedstawione w tabeli 13.6. 

 

Tabela 13.6. 

Domyślne foldery wykorzystywane przez mechanizm składowania izolowanego. 

System operacyjny 

PołoŜenie 

Windows 95, 98, Me 

c:\Windows\Ustawienia lokalne\Dane aplikacji 

Windows NT 4.0 

c:\WinNT\Profile\<uŜytkownik>\Dane aplikacji 

Windows NT 4.0 (z Service 
Pack 4) oraz Windows 2000 
(uaktualnienie Win NT 4.0) 

c:\WinNT\Profile\<uŜytkownik>\Ustawienia lokalne\Dane aplikacji 

background image

Windows 2000 (instalacja 
„czysta”, czyli bez 
uaktualniania innego 
systemu Windows — 95, 98, 
Me bądź WinNT 3.51) 

c:\Documents and Settings\<uŜytkownik>\Ustawienia lokalne\Dane 
aplikacji 

 

Na przykład, po wykonaniu strony z listingu 13.6 na serwerze IIS działającym w systemie 
Windows 2000 (zainstalowanym bez uaktualniania innych wersji systemu Windows), naleŜy 
przejść do folderu 

c:\Documents and Settings\Default User\Ustawienia lokalne\Dane 

aplikacji\Microsoft

. W folderze tym powinien znajdować się folder o nazwie 

IsolatedStorage

Wewnątrz niego powinny się znajdować inne foldery, wykorzystywane przez ASP.NET do 
przechowywania informacji o wykonywanych czynnościach, a oprócz nich — takŜe plik 

colors.txt

 

utworzony w wierszu 11. listingu 13.6. Zazwyczaj, to co się dzieje w tych folderach nie będzie 
miało najmniejszego znaczenia, jednak znajomość fizycznego połoŜenia plików moŜe się czasami 
okazać przydatna. 

Dost

ę

p do plików zapisanych w obszarach 

izolowanych 

Dane przechowywane przy wykorzystaniu mechanizmu składowania izolowanego są separowane 
przy uŜyciu dwóch róŜnych metod: uŜytkownika i komponentu oraz uŜytkownika, komponentu i 
domeny. UŜycie pierwszej metody oznacza, Ŝe izolowany obszar składowania będzie tworzony dla 
kaŜdej aplikacji z której korzysta uŜytkownik. Na przykład, plik zapisany w obszarze izolowanym 
przez uŜytkownika A korzystającego z aplikacji A, nie będzie dostępny dla tego samego 
uŜytkownika korzystającego z aplikacji B. Druga metoda dodatkowo uwzględnia domenę 
aplikacji. W kontekście ASP.NET oznacza to po prostu adres URL aplikacji. 

Być moŜe przypominasz sobie, Ŝe strony ASP.NET są kompilowane do postaci dynamicznie 
generowanych komponentów .NET (informacje na ten temat podawałem w rozdziale 2). Oznacza 
to, Ŝe w normalnych okolicznościach, Ŝadne dwie strony ASP.NET nie będą korzystały z tego 
samego komponentu .NET; a to z kolei oznacza, Ŝe Ŝadne dwie strony ASP.NET nie mogą 
uzyskać dostępu do tego samego izolowanego obszaru składowania. Idea ta została przedstawiona 
na rysunku 13.9. 

 

Do odczytywania danych przechowywanych w obszarach izolowanych wykorzystywane są 
obiekty klasy 

IsolatedStorageFileStream

. Przykład ich uŜycia przedstawiony został na 

listingu 13.7. 

 

Listing 13.7. 

Odczyt danych z obszarów izolowanych przy wykorzystaniu obiektów klasy 

IsolatedStorageFileStream

 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.IO" %> 

3

 

<%@ Import Namespace="System.IO.IsolatedStorage" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   sub Page_Load(obj as object, e as eventargs) 

7

 

      dim stream as new IsolatedStorageFileStream _ 

8

 

         ("colors.txt", FileMode.OpenOrCreate) 

9

 

      dim objReader as new StreamReader(stream) 

10

 

       

11

 

      while objReader.Peek() > -1 

12

 

         Response.Write(Server.HTMLEncode _ 

13

 

            (objReader.ReadLine) & "<br>") 

14

 

      end while 

15

 

      objReader.Close 

16

 

   end sub 

17

 

</script> 

18

 

 

19

 

<html><body> 

background image

20

 

   <asp:Label id="lblMessage" runat="server" /> 

21

 

</body></html> 

 

Kod powyŜszego listingu na pewno wygląda znajomo, gdyŜ nie ma w nim Ŝadnych nowych 
metod. Wykonanie tej strony powinno spowodować wyświetlenie słowa „niebieski”, które zostało 
zapisane w pliku umieszczonym w obszarze izolowanym przez stronę z listingu 13.6. 

Notatka 
Zwró

ć

 uwag

ę

, i

Ŝ

 wykonania powy

Ŝ

szej strony nie musi spowodowa

ć

 wy

ś

wietlenia jakichkolwiek 

wyników. Przypomnij sobie, 

Ŝ

e dwie ró

Ŝ

ne strony ASP.NET nie mog

ą

 uzyska

ć

 dost

ę

pu do tego 

samego  izolowanego  obszaru  składowania.  Oznacza  to, 

Ŝ

e  strona  z  listingu  13.7  nie  mo

Ŝ

korzysta

ć

  z  obszaru  u

Ŝ

ywanego  przez  stron

ę

  z  listingu  13.6.  Problem  ten  mo

Ŝ

na  rozwi

ą

za

ć

 

umieszczaj

ą

c  kody  z  obu  listingów  w  jednym  dokumencie  (to  samo  dotyczy  kodów 

przedstawionych na listingach 13.6 oraz 13.8). 

Nieco inaczej wygląda sprawa w przypadku odczytywania danych przechowywanych w obszarach 
izolowanych, przy uŜyciu obiektów klasy 

IsolatedStorageFile

. W tym przypadku, w 

pierwszej kolejności naleŜy pobrać odwołanie do pliku przechowywanego w izolowanym obszarze 
składowania, a dopiero później moŜna uŜyć obiektu klasy 

IsolatedStorageFile

 do wykonania 

jakichś operacji na tym pliku. Proces ten demonstruje przykład przedstawiony na listingu 13.8. 

 

Listing 13.8. 

Odczyt danych z pliku przechowywanego w obszarze izolowanym przy uŜyciu 

obiektu 

IsolatedStorageFile

 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.IO" %> 

3

 

<%@ Import Namespace="System.IO.IsolatedStorage" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   sub Page_Load(obj as object, e as eventargs) 

7

 

      dim i as Integer 

8

 

      dim objISOFile as IsolatedStorageFile = _ 

9

 

         IsolatedStorageFile.GetUserStoreForDomain() 

10

 

 

11

 

      lblMessage.Text = "<b>Pliki:</b> " 

12

 

      dim intCount = Ubound(objISOFile.GetFileNames("*.*")) 

13

 

      for i = 0 to intCount 

14

 

         lblMessage.Text += objISOFile.GetFileNames _ 

15

 

            ("*.*")(i) & "<br>" 

16

 

      next 

17

 

 

18

 

      lblMessage.Text += "<b>Komponenty .NET: </b>" & _ 

19

 

         objISOFile.AssemblyIdentity.ToString & "<br>" 

20

 

      lblMessage.Text += "<b>Domena: </b>" & _ 

21

 

         objISOFile.DomainIdentity.ToString & "<br>" 

22

 

      lblMessage.Text += "<b>Aktualna wielko

ść

: </b>" & _ 

23

 

         objISOFile.CurrentSize.ToString & "<br>" 

24

 

      lblMessage.Text += "<b>Maksymalna wielko

ść

: </b>" & _ 

25

 

         objISOFile.MaximumSize.ToString & "<br>" 

26

 

   end sub 

27

 

</script> 

28

 

 

29

 

<html><body> 

30

 

   <asp:Label id="lblMessage" runat="server" /> 

31

 

</body></html> 

 

 

Analiza 

W wierszach 8. i 9. tworzony jest obiekt 

IsolatedStorageFile

. Metoda 

IsolatedStorageFile.GetUserStoreForDomain

 zwraca obiekt klasy 

IsolatedStorageFile

 wybrany dla danego uŜytkownika, komponentu oraz domeny. Metoda 

IsolatedStorageFile.GetUserStoreForAssembly

 zwraca natomiast obszar izolowany dla 

konkretnego uŜytkownika i komponentu. 

Metoda 

GetFileNames

 zwraca tablicę zawierającą listę nazw plików spełniających podane 

kryteria; w naszym przypadku jest to 

"*.*"

. W wierszach od 13. do 16. wszystkie elementy tej 

background image

tablicy są pobierane, a zapisane w nich nazwy plików są wyświetlane w elemencie sterującym 

Label

. Podobne czynności wykonuje metoda 

GetDirectoryNames

, która takŜe umoŜliwia 

podanie łańcucha znaków określającego kryteria filtrowania zwracanych wyników. 

W końcu, w wierszach od 18. do 25. są wyświetlane właściwości izolowanego obszaru 
składowania. Właściwość 

AssemblyIdentity

 zwraca URL określający komponent .NET 

któremu odpowiada dany izolowany obszar składowania (czyli dynamiczny komponent 
wygenerowany przez środowisko .NET dla aplikacji WWW). Właściwość 

DomainIdentity

 

określa domenę skojarzoną z danym izolowanym obszarem składowania (przypomina ona nieco 
właściwość 

Domain

 obiektów reprezentujących cookies). Właściwości 

CurrentSize

 oraz 

MaxSize

 określają wielkość obszaru składowania naleŜącego do bieŜącego uŜytkownika, 

wyraŜoną w bajtach. Wyniki wykonania powyŜszego kodu przedstawione zostały na rysunku 
13.10. 

 

 

Rysunek 13.10.  Prezentacja informacji o izolowanym obszarze składowania, moŜliwa dzięki 
wykorzystaniu obiektu IsolatedStorageFile 

 

Na podstawie obiektu 

IsolatedStorageFile

 moŜna stworzyć obiekt 

IsolatedStorageFileStream

, a następnie uŜyć obiektu 

StreamReader

 do odczytania 

zawartości wybranego pliku: 

dim objISOFile as IsolatedStorageFile = _  
  IsolatedStorageFile.GetUserStoreForDomain() 
dim stream as new IsolatedStorageFileStream _ 
  ("options.txt", FileMode.OpenOrCreate, objISOFile ) 
 

To nie jest ASP! 

Operacje wejścia/wyjścia we wcześniejszych wersjach technologii ASP były wykonywane za 
pośrednictwem obiektów klasy 

FileSystem

. Udostępniała ona te same moŜliwości funkcjonalne 

co klasy omówione w tym rozdziale. ASP.NET ma moŜliwość wykorzystania wszystkich klas 
dostępnych w środowisku .NET, co oznacza, Ŝe w odróŜnieniu od wcześniejszych wersji 
technologii ASP, w ASP.NET moŜna wykonywać te same operacje wejścia/wyjścia co w 
tradycyjnych, niezaleŜnych aplikacjach. 

 

background image

Na szczęście, wiele rozwiązań stosowanych w ASP.NET, a nawet składnia ich implementacji, 
przypomina analogiczne rozwiązania uŜywane we tradycyjnej wersji technologii ASP. Zmieniły 
się nazwy kilku klas oraz niewidoczne dla programistów sposoby implementacji niektórych 
moŜliwości funkcjonalnych; jednak programiści znający zasady posługiwania się obiektami klasy 

FileSystemObject

 nie powinni mieć problemów z przejściem do nowych metod 

wykorzystywania plików. 

Jedną z najwaŜniejszych zmian, jest przejście do całkowicie obiektowej architektury. W 
ś

rodowisku .NET kaŜdy plik oraz folder moŜe być reprezentowany przez obiekt, a kaŜdy z tych 

obiektów udostępnia własne metody, właściwości oraz kolekcje dodatkowych obiektów. 
Przywyknięcie do stosowania tych ściśle ze sobą powiązanych obiektów moŜe zabrać nieco czasu, 
zwłaszcza, iŜ znacznie róŜnią się one od obiektów 

FileSystemObject

W ASP.NET zmieniły się takŜe zasady dołączania plików. Dzięki metodom interakcji ASP.NET 
ze środowiskiem .NET, dołączania zawartości plików do aplikacji ASP.NET jest bardzo proste. 
Tradycyjna technologia SSI wciąŜ jest dostępna, jednak moŜna wykorzystać wiele innych metod 
dołączania plików i rozszerzania w ten sposób moŜliwości funkcjonalnych stron ASP.NET. 

Natomiast składowanie izolowane jest całkowicie nową metodą przechowywania danych i dostępu 
do plików. Eliminuje on wiele problemów napotykanych wcześniej przy tworzeniu rozwiązań 
słuŜących do przechowywania informacji skojarzonych z uŜytkownikami. Oprócz cookies i baz 
danych, tradycyjna technologia ASP nie udostępniała Ŝadnych wbudowanych metod słuŜących do 
trwałego przechowywania danych skojarzonych z konkretnymi uŜytkownikami. Ale czemu 
rezygnować z zastosowania cookies? OtóŜ przy uŜyciu mechanizmu składowania izolowanego 
moŜna przechowywać znacznie więcej informacji niŜ w cookies, co z kolei umoŜliwia znacznie 
dalej idące dostosowanie aplikacji do potrzeb i oczekiwań uŜytkowników. Poza tym mechanizm 
składowania izolowanego jest znacznie łatwiejszy do wykorzystania niŜ cookies, pliki 
przechowywane w ten sposób mogą być składowane zarówno na serwerze jak i na komputerze 
uŜytkownika, a co waŜniejsze, rozwiązanie to udostępnia znacznie lepsze mechanizmy 
zabezpieczeń. 

Przewaga mechanizmu składowania izolowanego nad bazami danych nie jest aŜ tak oczywista. 
Wykorzystanie jednego lub drugiego rozwiązania będzie zaleŜeć od konkretnej sytuacji oraz 
konfiguracji serwera. Niemniej jednak obie te metody są niezwykle przydatne przy trwałym 
przechowywaniu danych.