|
|
1. sor: |
1. sor: |
| <cim | | <cim |
- | cim3="File-ból olvasás és írás" | + | cim3="Előírt lépésszámú ciklusok" |
| cim2="Magasszintű Programozási Nyelvek I." | | cim2="Magasszintű Programozási Nyelvek I." |
| cim1="Imperatív, procedurális nyelvek alapjai" | | cim1="Imperatív, procedurális nyelvek alapjai" |
- | prev="mp1/page550" | + | prev="mp1/page310" |
- | next="mp1/page900" | + | next="mp1/page400" |
| kep="hz_csik.png" | | kep="hz_csik.png" |
- | back="EBooks" | + | back="mp1/Nyitolap" |
| szerzo="hz|Hernyák Zoltán" | | szerzo="hz|Hernyák Zoltán" |
| /> | | /> |
15. sor: |
15. sor: |
| | | |
| | | |
- | = Text file = | + | = Előírt lépésszámú ciklusok = |
- | | + | |
- | A program futása során sok adatot képes előállítani, illetve sok adatot kell bekérni, amelyekkel számolni tud. Nagyon gyakori az az eset, amikor az előállított adatokat kiírjuk diszkre valamilyen file-ba. Ennek oka, hogy ott tartósan (a gép kikapcsolása esetén) is megmaradnak ezek a részeredmények, illetve ez az egyik legegyszerűbb módja annak, hogy másik program felé az adatokat publikáljuk (egyik program kiírja, másik program beolvassa).
| + | |
- | | + | |
- | A legegyszerűbb felépítésű file az ún. ''text file'' szerkezet. Az ilyen file-ok sorokra tagoltak, és tartalmukat akár a legegyszerűbb windows-os ''Jegyzettömb'' (notepad) alkalmazással is megtekinthető, szerkeszthető.
| + | |
- | | + | |
- | A text file-ok sorokat (string) tartalmaznak. Minden sor végét speciális sorvége jel zárja, amely windows-ban a \r\n karakterek (13,10 kódú karakterek), Linux alatt a \n (10 kódú karakter) van használatban. Ez persze nem annyira lényeges információ, csak ha olyan alkalmazást akarunk írni, amely mindkét platformon futásképes kell legyen.
| + | |
- | | + | |
- | <box type="stop">A text file kezeléshez szükséges dolgok a '''System.IO''' névtérben vannak, ezért a '''using System.IO;''' sort bele kell írni a programunk elejére!</box>
| + | |
- | | + | |
- | == Text file írása ==
| + | |
- | | + | |
- | Az íráshoz a '''StreamWriter'''-t kell használni, megadván a létrehozandó file nevét:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | string fname=@"c:\adatok.txt";
| + | |
- | StreamWriter w = new StreamWriter(fname, false, Encoding.Default);
| + | |
- | </code>
| + | |
- | | + | |
- | * az első paraméter (''fname'') adja meg a file nevét, amelybe írni szeretnénk.
| + | |
- | * a második paraméter (''false'') azt adja meg, hogy amennyiben ilyen nevű file lenne már, akkor azt a rendszer törölje le, és üres állapotból induljon a fileba írás. Ha ide ''true''-t adunk meg, akkor a már létező file tartalma megmarad, és amit most írunk bele majd a file-ba, az annak a végére fog íródni (hozzáfűzés, append).
| + | |
- | * a harmadik paraméter a file-ba írás kódlapját adja meg. Az ''Encoding.Default'' a windows-unkban használt kódlap (alapértelmezett kódlap)
| + | |
- | | + | |
- | A fentiek után a file-ba írás máris indulhat. Az íráshoz a már ismerős ''WriteLine''-t kell használni, csak nem a konzolra írunk (''Console.WriteLine''), hanem a file-ba szeretnénk írni, melyet most a ''w'' változónk azonosít. E miatt ''w.WriteLine''-t kell megadnunk:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | double r=23.4;
| + | |
- | w.WriteLine("Programozó=Hernyák Zoltán");
| + | |
- | w.WriteLine("PI={0}",Math.PI);
| + | |
- | w.WriteLine("sugár={0}",r);
| + | |
- | w.WriteLine("Kerület={0}",2*r*Math.PI);
| + | |
- | ...
| + | |
- | </code>
| + | |
- | | + | |
- | Ha minden adatot beleírtunk a file-ba, akkor a végén le kell azt zárnunk a ''Close()'' hívásával:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | w.Close();
| + | |
- | </code>
| + | |
- | | + | |
- | <box type="stop">Amennyiben elfelejtjük lezárni a file-t, úgy a kiírt adatok nem kerülnek bele! Ezért ezt a lépést semiképp ne felejtsük el!</box>
| + | |
- | | + | |
- | A teljes kód:
| + | |
- | <code lang="csharp">
| + | |
- | using System.IO;
| + | |
- | | + | |
- | string fname=@"c:\adatok.txt";
| + | |
- | StreamWriter w = new StreamWriter(fname, false, Encoding.Default);
| + | |
- | double r=23.4;
| + | |
- | w.WriteLine("Programozó=Hernyák Zoltán");
| + | |
- | w.WriteLine("PI={0}",Math.PI);
| + | |
- | w.WriteLine("sugár={0}",r);
| + | |
- | w.WriteLine("Kerület={0}",2*r*Math.PI);
| + | |
- | w.Close();
| + | |
- | </code>
| + | |
- | | + | |
- | Eredménye megtekinthető a jegyzettömb segítségével:
| + | |
- | | + | |
- | <kep width="440" style="margin-left:125px;" kep1="xx_adatok_txt.png">A file tartalma a Jegyzettömb-ben</kep>
| + | |
- | | + | |
- | == File-ból olvasás ==
| + | |
- | | + | |
- | A fileból olvasáshoz a '''StreamReader'''-t kell használni. A
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | string fname = @"c:\adatok.txt";
| + | |
- | StreamReader r = new StreamReader(fname, Encoding.Default);
| + | |
- | </code>
| + | |
- | | + | |
- | A megnyitás során meg kell adni
| + | |
- | * a file nevét (''fname'')
| + | |
- | * a file-ba íráskor használt kódlapot (ez most is a windows-unk alapértelmezett kódlapja lesz, ''Encoding.Default'')
| + | |
- | | + | |
- | A file-ból olvasás során a ''ReadLine()''-t kell használni, csak épp most nem a konzolról olvasunk (Console.ReadLine()), hanem a file-ból. A file-unkat most az ''r'' változó képviseli, ezért '''r.ReadLine()'''-al kell olvasni. A ''ReadLine'' most is string-et ad meg. Minden egyes olvasás során a file-unk egy-egy sorát kapjuk meg:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | string s;
| + | |
- | s = r.ReadLine(); // "Programozó: Hernyák Zoltán"
| + | |
- | s = r.ReadLine(); // "PI=3,14159265358979"
| + | |
- | s = r.ReadLine(); // "sugár=23,4"
| + | |
- | s = r.ReadLine(); // "Kerület=147,026536188002"
| + | |
- | </code>
| + | |
- | | + | |
- | Amikor befejezzük a file-ból olvasást, akkor a file-t le kell zárni a ''Close()'' segítségével:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | r.Close();
| + | |
- | </code>
| + | |
- | | + | |
- | A teljes kód:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | using System.IO;
| + | |
- | | + | |
- | string fname = @"c:\adatok.txt";
| + | |
- | StreamReader r = new StreamReader(fname, Encoding.Default);
| + | |
- | string s;
| + | |
- | s = r.ReadLine(); // "Programozó: Hernyák Zoltán"
| + | |
- | s = r.ReadLine(); // "PI=3,14159265358979"
| + | |
- | s = r.ReadLine(); // "sugár=23,4"
| + | |
- | s = r.ReadLine(); // "Kerület=147,026536188002"
| + | |
- | r.Close();
| + | |
- | </code>
| + | |
- | | + | |
- | | + | |
- | == Minden sor beolvasása ==
| + | |
- | | + | |
- | Amennyiben tudjuk előre, hogy a text file-unk 4 sorból áll, akár ciklust is szervezhetünk hozzá:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | using System.IO;
| + | |
- | | + | |
- | string fname = @"c:\adatok.txt";
| + | |
- | StreamReader r = new StreamReader(fname, Encoding.Default);
| + | |
- | for (int i=0;i<4;i++)
| + | |
- | {
| + | |
- | string s = r.ReadLine();
| + | |
- | ...
| + | |
- | }
| + | |
- | r.Close();
| + | |
- | </code>
| + | |
- | | + | |
- | Ne rontsuk el: a file bezárását nem a ciklusban, hanem a cikluson kívül csak a legvégén kell megtenni!
| + | |
- | | + | |
- | Sokkal gyakoribb eset, amikor nem tudjuk előre, hogy a text file-unk hány sorból áll. Ekkor a fenti ''for'' ciklus nem használható, helyette ''while'' ciklust fogalmazunk. A feltételben azt kérdezzük le, hogy elértük-e már (end of file, end of stream) a text file végét.
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | using System.IO;
| + | |
- | | + | |
- | string fname = @"c:\adatok.txt";
| + | |
- | StreamReader r = new StreamReader(fname, Encoding.Default);
| + | |
- | while (!r.EndOfStream)
| + | |
- | {
| + | |
- | string s = r.ReadLine();
| + | |
- | ...
| + | |
- | }
| + | |
- | r.Close();
| + | |
- | </code>
| + | |
- | | + | |
- | == Substring ==
| + | |
- | | + | |
- | Tegyük fel, hogy a beolvasó program szeretné tudni, mennyi volt a sugár értéke. Hogyan szedjük ki ezt az információt a text file-ból?
| + | |
- | | + | |
- | Ehhez tudnunk kell, hogy a keresett adat a ''sugár='' sorban található, az egyenlőség jel jobb oldalán. Minden egyes sort beolvasunk, keresvén azt a sort, amelyiknek az eleje pontosan ez a karaktersorozat:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | while (!r.EndOfStream)
| + | |
- | {
| + | |
- | string s = r.ReadLine();
| + | |
- | if (s.StartsWith("sugár=")) Console.WriteLine(s);
| + | |
- | ...
| + | |
- | }
| + | |
- | </code>
| + | |
- | | + | |
- | A ''StartsWith''-el lehet a stringünk (sorunk) elejét megvizsgálni. A fenti ''if'' ki fogja keresni ezt a sort, és jelenleg ezt a sort kiírjuk a képernyőre.
| + | |
- | | + | |
- | De hogyan vegyük ki magát a számértéket a sorból? Le kell választani az ''s'' stringünkből ezt a darabkát a ''Substring()'' segítségével. Ennek meg kell adni:
| + | |
- | * hanyadik betűtől akarjuk leválasztani
| + | |
- | * hány betű hosszú darabot
| + | |
- | | + | |
- | Ezzel két gond is van: a ''hanyadik betű'' megadásakor ügyeljünk rá, hogy a betűk sorszámozása 0-tól kezdődik. A ''sugár=23,4'' szövegünkben a ''23,4'' szakasz a 6 betűtől kezdődik, és 4 betű hosszú:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | if (s.StartsWith("sugár="))
| + | |
- | {
| + | |
- | string szam = s.Substring(6,4); // "23,4"
| + | |
- | double sugar = double.Parse(szam);
| + | |
- | Console.WriteLine("sugar beolvasas utan={0}",sugar);
| + | |
- | }
| + | |
- | </code>
| + | |
- | | + | |
- | == Split ==
| + | |
- | | + | |
- | Másik (és sokkal jobb módszer) a ''Split'' használata. A Split segítségével egy sztringet több felé vághatunk szét valamilyen elválasztó karakter mentén. A ''sugár=23,4'' sort kettévághatjuk az '''=''' jel mentén két darabra, így különválik a bal oldali rész ''sugár'' és a jobb oldali rész ''23,4''. A kettévágás egy string[] tömböt eredményez. A tömbünk két elemű lesz, a 0 sorszámú elem az első darab, a 1 sorszámú elem pedig a második darabka lesz:
| + | |
- | | + | |
- | <code lang="csharp">
| + | |
- | if (s.StartsWith("sugár="))
| + | |
- | {
| + | |
- | string[] darabok = s.Split('='); // "23,4"
| + | |
- | double sugar = double.Parse(darabok[1]);
| + | |
- | Console.WriteLine("sugar beolvasas utan={0}",sugar);
| + | |
- | }
| + | |
- | </code>
| + | |
- | | + | |
- | Miért jobb a ''Split'' mint a ''Substring''? Ugyanis ha az értékünk nem ''23,4'', hanem mondjuk ''123,345''', amely már nem 4 karakter hosszú, akkor a fenti Substring máris nem jól működik. Van persze arra mód, hogy ezen segítsünk a string hosszából (s.Length) kiindulva, de a ''Split'' annyival egyszerűbben működik, hogy kár ezzel foglalkozni.
| + | |
- | | + | |
- | | + | |
| | | |
| | | |
| <alairas>Hernyák Zoltán</alairas> | | <alairas>Hernyák Zoltán</alairas> |
| __NOTOC__ | | __NOTOC__ |