PDA-applikationer med .NET: Lektion 10

Idag:
  • Minnet i en handdator
  • Att skriva och läsa filer i .NET Compact Framework
  • Kort om annan kommunikation: till minnet och via nätverk

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)

Hur minnet är uppdelat i Windows CE

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.

Filsystemet i Windows CE

Bild 5: File Explorer

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?

  1. Manipulering av hela filer och kataloger (till exempel för att byta namn på en fil)
  2. Läsning och skrivning av byte-strömmar
  3. 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

Ett litet testprogram

Bild(er) 11: Det lilla testprogrammet

Ett litet testprogram     Ett litet testprogram

"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

"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!

Hur man kan sätta ihop byte-strömmar med läsare/skrivare

"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

Programmet TextEdit

Bild 30: Filväljardialogen

Programmet TextEdit     Programmet TextEdit

Bild 31: Internet Explorer

Internet Explorer

Bild 32: En riktigt dålig webbläsare

Fånigt enkel webbläsare

Bild 33: Provkörning av den riktigt dåliga webbläsaren

Fånigt enkel webbläsare     Fånigt enkel webbläsare

"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. Här är några frågor som kan användas som instuderingsfrågor:
  1. En Pocket PC-handdator brukar inte ha någon hårddisk. Varför?
  2. Hur har Pocket PC löst problemet med lagring av data, nu när det (normalt) inte finns någon hårddisk?
  3. Vad används ROM-minnet till på Pocket PC?
  4. RAM-minnet på Pocket PC används till programminne (dvs de körande programmens arbetsdata) och objektlagret ("the object store"). Vad innehåller objektlagret?
  5. Vad menas med kallstart ("cold boot") och varmstart ("warm boot")?
  6. 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?
  7. Ett filsystem består av kataloger och filer. Vilka likheter och skillnader finns mellan filsystemet på skrivbords-Windows och Windows CE?
  8. Hur kommer man åt de filer som lagras på minneskorten?
  9. Hur kopierar man en fil inifrån ett C#-program?
  10. Varför kan man inte skapa ett Stream-objekt, till exempel med kodsnutten new Stream()?
  11. 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?
  12. 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?
  13. 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?
  14. Hur läser du in smurferna från binärfilen?
  15. Hur skriver du smurfer på en textfil?
  16. 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.)
  17. 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

  1. 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?
  2. 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.
  3. 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.
  4. 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