Klicka på startknappen i den lilla mediaspelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediaspelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca 39 minuter, ca 18 megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag. Tänk på att lektionerna ger en översikt och introduktion. Du måste läsa i kursboken och (viktigast!) arbeta med övningarna för att tillgodogöra dig kursen. "Bild" 1: Olika typer av minne i en skrivbordsdator Typ Storlek Snabbhet Läsning Skrivning Finns kvar Användning RAM Litet Snabbt Ja Ja Nej Programminne ROM Litet Snabbt Ja Nej/Sällan Ja BIOS Disk Stort Långsamt Ja Ja Ja Filer, swap, OS "Bild" 2: Olika typer av minne i en handdator Typ Storlek Snabbhet Läsning Skrivning Finns kvar Användning RAM Litet Snabbt Ja Ja Ja! Programminne, filer ROM Litet Snabbt Ja Nej/Sällan Ja OS Bild 3: Minnet i Windows CE (och därmed Pocket PC) Bild 4: Filsystemet i Windows CE Skrivbords-Windows har "enheter", som C: och D:, och under varje enhet finns ett träd. En fil kan ha det fullständiga namnet C:\En katalog\En underkatalog\Filnamnet.txt Windows CE har inga enheter, och bara ett enda träd. En fil kan ha det fullständiga namnet \En katalog\En underkatalog\Filnamnet.txt Ingen aktuell katalog. Bild 5: File Explorer "Bild" 6: Filhantering i Windows CE - varför? Varför filer? Både programminnet och filerna lagras ju i samma RAM-minne? Både programminnet och filerna finns kvar lika mycket (eller försvinner om batteriet tar slut)? Programmen avslutas (oftast) inte? Jo: Formatet (dvs hur data organiseras) kan göras annorlunda Sparning av flera versioner eller så man kan backa Flyttning (t ex vid synkning) "Bild" 7: Filhantering i Windows CE - hur? Manipulering av hela filer och kataloger (till exempel för att byta namn på en fil) Läsning och skrivning av byte-strömmar Läsning och skrivning av värden, strängar och text "Bild" 8: Att jobba med kataloger Man använder statiska metoder i klassen Directory. using System.IO; Directory.CreateDirectory("\\My Documents\\testdir1"); Directory.CreateDirectory(@"\My Documents\testdir2"); Directory.CreateDirectory("\\testdir3"); Directory.CreateDirectory("testdir4"); Directory.Move("\\My Documents\\testdir1", "\\My Documents\\flyttat-testdir1"); if (Directory.Exists("\\My Documents\\flyttat-testdir1")) print("Katalogen finns."); "Bild" 9: Att jobba med filer Man använder statiska metoder i klassen File. using System.IO; File.Create("\\testdir\\testfil1.txt"); File.Move("\\testdir\\testfil2.txt", "\\testdir\\flyttad-testfil2.txt"); if (File.Exists("\\testdir\\flyttad-testfil2.txt")) print("Filen finns."); File.Delete("\\testdir\\flyttad-testfil2.txt"); Bild 10: Ett litet testprogram Hela källkoden till programmet: Skriv-och-las-test.cs Bild(er) 11: Det lilla testprogrammet "Bild" 12: Metoden print private void print(string s) { textboxen.Text = textboxen.Text + s + "\r\n"; } "Bild" 13: Skrivning på en fil med hjälp av en byte-ström Ett FileStream-objekt är en öppen byte-ström som är kopplad till en fil i filsystemet. print("Skapar en byte-fil..."); FileStream fs = new FileStream("\\testfil-1.bin", FileMode.Create, FileAccess.Write); fs.WriteByte(72); fs.WriteByte(101); fs.WriteByte(106); fs.WriteByte(33); fs.Close(); Man kan öppna byte-strömmar inte bara till filer, utan även till en plats i minnet (MemoryStream), och till en annan dator på nätverket (NetworkStream). "Bild" 14: Läsning från en fil med hjälp av en byte-ström Ett FileStream-objekt är en öppen byte-ström som är kopplad till en fil i filsystemet. print("Läser byte-filen..."); FileStream fs = new FileStream("\\testfil-1.bin", FileMode.Open, FileAccess.Read); int b; string s = ""; while ((b = fs.ReadByte()) != -1) { print("Byte: " + b); s += (char)b; } fs.Close(); print("Läst: '" + s + "'"); "Bild" 15: Utmatningen i textboxen Läser byte-filen... Byte: 72 Byte: 101 Byte: 106 Byte: 33 Läst: 'Hej!' "Bild" 16: Skrivning på en textfil Ett StreamWriter-objekt är en öppen textström som är kopplad till, till exempel, en fil i filsystemet. using System.Text; print("Skapar en textfil..."); TextWriter tw = new StreamWriter("\\testfil-2.txt"); tw.WriteLine("Ena raden."); tw.WriteLine("En rad med ÅÄÖ och åäö."); tw.WriteLine("Tredje och sista raden."); tw.Close(); "Bild" 17: Läsning från en textfil Ett StreamReader-objekt är en öppen textström som är kopplad till, till exempel, en fil i filsystemet. using System.Text; print("Läser textfilen..."); TextReader tr = new StreamReader("\\testfil-2.txt"); string rad; while ((rad = tr.ReadLine()) != null) print("Rad: " + rad); tr.Close(); "Bild" 18: Utmatningen i textboxen Läser textfilen... Rad: Ena raden. Rad: En rad med ÅÄÖ och åäö. Rad: Tredje och sista raden. "Bild" 19: Kodningar av text Internt i Windows CE (och därför, Pocket PC) är alla tecken (char) och strängar (string) i Unicode. Unicode: 16 bitar, kan hantera å, ä, ö och tusentals andra konstiga tecken. En fil som ska lagras skrivs normalt inte i Unicode, utan någon kodning. En vanlig kodning är UTF-8. "Bild" 20: Vad innehåller testfil-2.txt, byte för byte? "UTF-8 Unicode text, with CRLF line terminators" 69 110 32 114 97 100 32 109 101 100 32 195 133 195 132 195 150 32 111 99 104 32 195 165 195 164 195 182 46 13 10 E n r a d m e d Å Ä Ö o c h å ä ö . "Bild" 21: Skrivning på en textfil med en annan kodning print("Skapar en textfil till, med annan kodning..."); Encoding kodning = Encoding.ASCII; TextWriter tw3 = new StreamWriter("\\testfil-5.txt", false, kodning); tw3.WriteLine("Ena raden."); tw3.WriteLine("En rad med ÅÄÖ och åäö."); tw3.WriteLine("Tredje och sista raden."); tw3.Close(); Bild 22: Byggklossar! "Bild" 23: Skrivning på en binärfil Ett BinaryWriter-objekt är en öppen binärström som är kopplad till, till exempel, en fil i filsystemet. print("Skapar en binärfil..."); FileStream fs2 = new FileStream("\\testfil-3.bin", FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs2); bw.Write(175); bw.Write("hej"); bw.Write(3.14); bw.Close(); Bara enkla datatyper, som heltal, strängar och flyttal. Objekt och structar måste skrivas (och läsas) ett fält i taget! "Bild" 24: Läsning från en binärfil Ett BinaryReader-objekt är en öppen binärström som är kopplad till, till exempel, en fil i filsystemet. print("Läser binärfilen..."); FileStream fs2 = new FileStream("\\testfil-3.bin", FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs2); print("Heltalet: " + br.ReadInt32()); print("Strängen: " + br.ReadString()); print("Flyttalet: " + br.ReadDouble()); br.Close(); "Bild" 25: Utmatningen i textboxen Läser binärfilen... Heltalet: 175 Strängen: hej Flyttalet: 3.14 "Bild" 26: Skrivning på en XML-fil Ett XmlWriter-objekt är en öppen XML-ström som är kopplad till, till exempel, en fil i filsystemet. using System.Xml; // XML-exempelkod hämtad från // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemxmlxmlwriterclasstopic.asp print("Skapar en XML-fil..."); TextWriter tw2 = new StreamWriter("\\testfil-4.xml"); XmlWriter xw = new XmlTextWriter(tw2); xw.WriteStartElement("root"); xw.WriteAttributeString("xmlns", "x", null, "urn:1"); xw.WriteStartElement("item","urn:1"); xw.WriteEndElement(); xw.WriteStartElement("item","urn:1"); xw.WriteEndElement(); xw.WriteEndElement(); xw.Close(); "Bild" 27: Vad innehåller testfil-4.xml? <root xmlns:x="urn:1"> <x:item /> <x:item /> </root> "Bild" 28: Läsning från en XML-fil Ett XmlReader-objekt är en öppen XML-ström som är kopplad till, till exempel, en fil i filsystemet. using System.Xml; print("Läser XML-filen..."); TextReader tr2 = new StreamReader("\\testfil-4.xml"); XmlReader xr = new XmlTextReader(tr2); // Här kan man läsa XML-filen xr.Close(); Bild 29: Exemplet ur boken med Anteckningar Bild 30: Filväljardialogen Bild 31: Internet Explorer Bild 32: En riktigt dålig webbläsare Bild 33: Provkörning av den riktigt dåliga webbläsaren "Bild" 34 (Överkurs): Nätverkskommunikation med socketar Klassen Socket är en öppen byte-ström som är kopplad till en fil. Radnumren ingår inte i programmet. Hela källkoden till programmet: Webblasare.cs 6 using System.Net; 7 using System.Net.Sockets; 84 private void knapp1_Click(object sender, System.EventArgs e) 85 { 86 string server = "basen.oru.se"; 87 int port = 80; 88 string sidan = SocketSendReceive(server, port); 89 print("Den hämtade webbsidan:"); 90 print(""); 91 print(sidan); 92 } 100 // Kod hämtad från 101 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp 102 103 private static Socket ConnectSocket(string server, int port) 104 { 105 Socket s = null; 106 IPHostEntry hostEntry = null; 107 108 // Get host related information. 109 hostEntry = Dns.Resolve(server); 110 111 // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid 112 // an exception that occurs when the host IP Address is not compatible with the address family 113 // (typical in the IPv6 case). 114 foreach(IPAddress address in hostEntry.AddressList) 115 { 116 IPEndPoint ipe = new IPEndPoint(address, port); 117 Socket tempSocket = 118 new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 119 120 tempSocket.Connect(ipe); 121 122 if(tempSocket.Connected) 123 { 124 s = tempSocket; 125 break; 126 } 127 else 128 { 129 continue; 130 } 131 } 132 return s; 133 } // ConnectSocket 134 135 // This method requests the home page content for the specified server. 136 private static string SocketSendReceive(string server, int port) 137 { 138 string request = "GET / HTTP/1.1\r\nHost: " + server + 139 "\r\nConnection: Close\r\n\r\n"; 140 Byte[] bytesSent = Encoding.ASCII.GetBytes(request); 141 Byte[] bytesReceived = new Byte[256]; 142 143 // Create a socket connection with the specified server and port. 144 Socket s = ConnectSocket(server, port); 145 146 if (s == null) 147 return ("Connection failed"); 148 149 // Send request to the server. 150 s.Send(bytesSent, bytesSent.Length, 0); 151 152 // Receive the server home page content. 153 int bytes = 0; 154 string page = "Default HTML page on " + server + ":\r\n"; 155 156 // The following will block until te page is transmitted. 157 do 158 { 159 bytes = s.Receive(bytesReceived, bytesReceived.Length, 0); 160 page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes); 161 } 162 while (bytes > 0); 163 164 return page; 165 } // SocketSendReceive Läsanvisningar Den här lektionen motsvaras av delar av kapitel 11, Storage. Läs introduktionen på s 735-750 för att repetera och fördjupa vad som sagts i den här lektionen. Läs översiktligt igenom exemplet med TextEdit-programmet, på s 749 och 751-770, mest för att få en lite mer matig överblick över vad man kan göra med I/O i .NET. Vi hoppar över avsnittet Registry Access på s 770-789. Registret ("the registry") används, både i skrivbords-Windows och Windows CE, för att lagra konfigurationsinformation för program. Det går inte att komma åt registret från hanterad kod ("managed code") i .NET, utan man måste gå via anrop i ohanterad kod. Dessutom verkar Microsoft nu ha börjat svänga lite, och tycker att det där med registret kanske inte var så bra ändå, utan man kan nog också använda vanliga filer för att lagra den informationen. Nätverkskommunikationen med sockets i webbläsarexemplet här ovan behöver du inte lära dig några detaljer från. Det räcker med att veta att det går att koppla upp sig mot en annan dator via ett nätverk, till exempel mot en webbserver för att hämta en webbsida, från ett C#-program i .NET Compact Framework. Här är några frågor som kan användas som instuderingsfrågor: En Pocket PC-handdator brukar inte ha någon hårddisk. Varför? Hur har Pocket PC löst problemet med lagring av data, nu när det (normalt) inte finns någon hårddisk? Vad används ROM-minnet till på Pocket PC? RAM-minnet på Pocket PC används till programminne (dvs de körande programmens arbetsdata) och objektlagret ("the object store"). Vad innehåller objektlagret? Vad menas med kallstart ("cold boot") och varmstart ("warm boot")? Du köper den tuffaste Pocket PC som finns att få tag på, med största möjliga minne och största möjliga antal platser för expansionskort. Självklart köper du också de rymligaste expansionskort du kan få tag på. En mp3-låt är ungefär 5 megabyte stor. Hur många mp3-låtar får du plats med på din Pocket PC? Ett filsystem består av kataloger och filer. Vilka likheter och skillnader finns mellan filsystemet på skrivbords-Windows och Windows CE? Hur kommer man åt de filer som lagras på minneskorten? Hur kopierar man en fil inifrån ett C#-program? Varför kan man inte skapa ett Stream-objekt, till exempel med kodsnutten new Stream()? Man kan alltså inte skapa ett Stream-objekt, men man kan skapa en variabel som har datatypen Stream. Vad ska det vara bra för, när man nu inte kan skapa några Stream-objekt att lägga i variabeln? Klasserna StreamReader och StringReader kan användas för att läsa text, till exempel med metoden ReadLine. Vad är det för skillnad på StreamReader och StringReader? Du har skapat följande struct-typ: struct Smurf { int smurfnummer; string namn; int status; double vikt; } Hur skriver du smurfer på en binärfil? Hur läser du in smurferna från binärfilen? Hur skriver du smurfer på en textfil? Hur läser du in smurferna från textfilen? (Varning: Den här frågan kan vara lite krånglig, så betrakta den som överkurs.) Du byter ut struct-typen Smurf mot en (nästan) likadan klass: class Smurf { int smurfnummer; string namn; int status; double vikt; } Hur gör du nu för att läsa och skriva dina smurfer på text- och binärfiler? Programmeringsövningar Skrivbords-Windows, och även till exempel Linux, arbetar med en aktuell katalog ("current directory"). Det står i boken att Windows CE inte använder sig av en sådan. Men i tabell 11.1 på sidan 743 har de tagit med metoderna GetCurrentDirectory och SetCurrentDirectory. Har de skrivit fel? Eller vad händer om man försöker använda dessa anrop? Skriv ett program som sparar lite data på en fil, och ett annat program som läser data från samma fil. Välj själv om det ska vara en binärfil, en textfil eller (överkurs!) en XML-fil. Kolla att det blir rätt. Låt de data som ska sparas på filen vara smurfer, som i instuderingsfrågorna. Välj själv om det ska vara en binärfil, en textfil eller (överkurs!) en XML-fil. Programmet som läser ska inte veta i förväg hur många smurfer som finns på filen. Kolla att det blir rätt. Ladda ner TextEdit-programmet från bokens webbplats, och provkör. Studera gärna koden också. Föregående lektion | Lektionslista | Nästa lektion Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 5 december 2005
Klicka på startknappen i den lilla mediaspelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediaspelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca 39 minuter, ca 18 megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag.
Windows CE har inga enheter, och bara ett enda träd. En fil kan ha det fullständiga namnet \En katalog\En underkatalog\Filnamnet.txt
Ingen aktuell katalog.
using System.IO;
Directory.CreateDirectory("\\My Documents\\testdir1"); Directory.CreateDirectory(@"\My Documents\testdir2"); Directory.CreateDirectory("\\testdir3"); Directory.CreateDirectory("testdir4"); Directory.Move("\\My Documents\\testdir1", "\\My Documents\\flyttat-testdir1"); if (Directory.Exists("\\My Documents\\flyttat-testdir1")) print("Katalogen finns.");
File.Create("\\testdir\\testfil1.txt"); File.Move("\\testdir\\testfil2.txt", "\\testdir\\flyttad-testfil2.txt"); if (File.Exists("\\testdir\\flyttad-testfil2.txt")) print("Filen finns."); File.Delete("\\testdir\\flyttad-testfil2.txt");
private void print(string s) { textboxen.Text = textboxen.Text + s + "\r\n"; }
print("Skapar en byte-fil..."); FileStream fs = new FileStream("\\testfil-1.bin", FileMode.Create, FileAccess.Write); fs.WriteByte(72); fs.WriteByte(101); fs.WriteByte(106); fs.WriteByte(33); fs.Close();
Man kan öppna byte-strömmar inte bara till filer, utan även till en plats i minnet (MemoryStream), och till en annan dator på nätverket (NetworkStream).
print("Läser byte-filen..."); FileStream fs = new FileStream("\\testfil-1.bin", FileMode.Open, FileAccess.Read); int b; string s = ""; while ((b = fs.ReadByte()) != -1) { print("Byte: " + b); s += (char)b; } fs.Close(); print("Läst: '" + s + "'");
Läser byte-filen... Byte: 72 Byte: 101 Byte: 106 Byte: 33 Läst: 'Hej!'
using System.Text;
print("Skapar en textfil..."); TextWriter tw = new StreamWriter("\\testfil-2.txt"); tw.WriteLine("Ena raden."); tw.WriteLine("En rad med ÅÄÖ och åäö."); tw.WriteLine("Tredje och sista raden."); tw.Close();
print("Läser textfilen..."); TextReader tr = new StreamReader("\\testfil-2.txt"); string rad; while ((rad = tr.ReadLine()) != null) print("Rad: " + rad); tr.Close();
Läser textfilen... Rad: Ena raden. Rad: En rad med ÅÄÖ och åäö. Rad: Tredje och sista raden.
69 110 32 114 97 100 32 109 101 100 32 195 133 195 132 195 150 32 111 99 104 32 195 165 195 164 195 182 46 13 10
E n r a d m e d Å Ä Ö o c h å ä ö .
print("Skapar en textfil till, med annan kodning..."); Encoding kodning = Encoding.ASCII; TextWriter tw3 = new StreamWriter("\\testfil-5.txt", false, kodning); tw3.WriteLine("Ena raden."); tw3.WriteLine("En rad med ÅÄÖ och åäö."); tw3.WriteLine("Tredje och sista raden."); tw3.Close();
print("Skapar en binärfil..."); FileStream fs2 = new FileStream("\\testfil-3.bin", FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs2); bw.Write(175); bw.Write("hej"); bw.Write(3.14); bw.Close();
Bara enkla datatyper, som heltal, strängar och flyttal. Objekt och structar måste skrivas (och läsas) ett fält i taget!
print("Läser binärfilen..."); FileStream fs2 = new FileStream("\\testfil-3.bin", FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs2); print("Heltalet: " + br.ReadInt32()); print("Strängen: " + br.ReadString()); print("Flyttalet: " + br.ReadDouble()); br.Close();
Läser binärfilen... Heltalet: 175 Strängen: hej Flyttalet: 3.14
using System.Xml;
// XML-exempelkod hämtad från // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemxmlxmlwriterclasstopic.asp print("Skapar en XML-fil..."); TextWriter tw2 = new StreamWriter("\\testfil-4.xml"); XmlWriter xw = new XmlTextWriter(tw2); xw.WriteStartElement("root"); xw.WriteAttributeString("xmlns", "x", null, "urn:1"); xw.WriteStartElement("item","urn:1"); xw.WriteEndElement(); xw.WriteStartElement("item","urn:1"); xw.WriteEndElement(); xw.WriteEndElement(); xw.Close();
<root xmlns:x="urn:1"> <x:item /> <x:item /> </root>
print("Läser XML-filen..."); TextReader tr2 = new StreamReader("\\testfil-4.xml"); XmlReader xr = new XmlTextReader(tr2); // Här kan man läsa XML-filen xr.Close();
Radnumren ingår inte i programmet.
Hela källkoden till programmet: Webblasare.cs
6 using System.Net; 7 using System.Net.Sockets;
84 private void knapp1_Click(object sender, System.EventArgs e) 85 { 86 string server = "basen.oru.se"; 87 int port = 80; 88 string sidan = SocketSendReceive(server, port); 89 print("Den hämtade webbsidan:"); 90 print(""); 91 print(sidan); 92 }
100 // Kod hämtad från 101 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp 102 103 private static Socket ConnectSocket(string server, int port) 104 { 105 Socket s = null; 106 IPHostEntry hostEntry = null; 107 108 // Get host related information. 109 hostEntry = Dns.Resolve(server); 110 111 // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid 112 // an exception that occurs when the host IP Address is not compatible with the address family 113 // (typical in the IPv6 case). 114 foreach(IPAddress address in hostEntry.AddressList) 115 { 116 IPEndPoint ipe = new IPEndPoint(address, port); 117 Socket tempSocket = 118 new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 119 120 tempSocket.Connect(ipe); 121 122 if(tempSocket.Connected) 123 { 124 s = tempSocket; 125 break; 126 } 127 else 128 { 129 continue; 130 } 131 } 132 return s; 133 } // ConnectSocket 134 135 // This method requests the home page content for the specified server. 136 private static string SocketSendReceive(string server, int port) 137 { 138 string request = "GET / HTTP/1.1\r\nHost: " + server + 139 "\r\nConnection: Close\r\n\r\n"; 140 Byte[] bytesSent = Encoding.ASCII.GetBytes(request); 141 Byte[] bytesReceived = new Byte[256]; 142 143 // Create a socket connection with the specified server and port. 144 Socket s = ConnectSocket(server, port); 145 146 if (s == null) 147 return ("Connection failed"); 148 149 // Send request to the server. 150 s.Send(bytesSent, bytesSent.Length, 0); 151 152 // Receive the server home page content. 153 int bytes = 0; 154 string page = "Default HTML page on " + server + ":\r\n"; 155 156 // The following will block until te page is transmitted. 157 do 158 { 159 bytes = s.Receive(bytesReceived, bytesReceived.Length, 0); 160 page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes); 161 } 162 while (bytes > 0); 163 164 return page; 165 } // SocketSendReceive
struct Smurf { int smurfnummer; string namn; int status; double vikt; }
class Smurf { int smurfnummer; string namn; int status; double vikt; }
Föregående lektion | Lektionslista | Nästa lektion