Dúfam, že sa vám táto téma páči. Po skončení kapitoly: práca so súbormi, by som chcel dať pre oddych (zaujímavosť), šifrovaný prístup k súborom prípadne ukážku čiastočného alebo úplného uzamknutia súboru. Ak vás to zaujalo, napíšte do diskusie či je to dobrá téma alebo navrhnite aj nejakú inú tému, čo sa týka súborov.
>>Práca so znakmi alebo celými riadkami
Príklad 23.1
//--------------------------------------------------
using System;
using System.IO;
class MainClass
{
private const string fileName="test.txt";
public static void Main(string[] args)
{
// Otvorenie suboru na zapisovanie
FileStream fs = new FileStream(fileName,FileMode.Create);
// Nadstavba zapisovania na FileStream
StreamWriter sw = new StreamWriter(fs);
// Zapis, kazdy na novy riadok
sw.WriteLine("Ahoj ");
sw.WriteLine("ako ");
sw.WriteLine("sa mas ");
sw.Close();
// Otvorenie existujuceho suboru
fs = new FileStream(fileName,FileMode.Open);
// Nadstavba citania na FileStream
StreamReader sr = new StreamReader(fs);
string temp=null;
// Citanie po riadkoch
while( (temp=sr.ReadLine()) !=null)
{
Console.WriteLine(temp);
}
sr.Close();
}
}
//--------------------------------------------------
Príklad na stiahnutie : www.inet.sk/download/user/Priklad23.1_CitaniePoRiadkoch.zip
Podobne ako bolo ukázané v minulom článku si najprv vytvoríme FileStream, kde si nastavíme typ prístupu k súboru. Teraz ale pridáme aj ďalšiu vrstvu a to StreamWriter, ktorý dokáže pracovať aj s textovými reťazcami a nie len s byt-mi ako FileStream.
Potom jednoducho zapisujeme text pomocou príkazu WriteLine() - aj hneď odriadkuje na rozdiel od toho, keby sme použili len Write(). Pri načítavaní tvorí nadstavbu na FileStream trieda StreamReader. (Trieda a podobné výrazy budú vysvetlené už čoskoro. K zbežnému pochopeniu príkladov to ešte nepotrebujeme vedieť)
Ak súbor je na konci a pokúsime sa ďalej čítať pomocou ReadLine(), tak výstupný reťazec sa rovná konštante null (voľne preložiteľné ako - prázdny).
Ak na konci súboru použijeme príkaz Read() tak výstupom bude -1.
>>Práca so slovami
Príklad 23.2
//--------------------------------------------------
using System;
using System.IO;
class MainClass
{
public static void Main(string[] args)
{
// Osetrenie ci subor existuje
if (File.Exists("test.txt") == false)
{
Console.WriteLine(" Subor test.txt neexistuje");
Console.ReadLine();
return;
}
// inic. prace so suborom na citanie
FileStream fs = new FileStream("test.txt",FileMode.Open);
StreamReader tr = new StreamReader(fs);
string slovo="";
int pismeno;
int oddelovac=' '; // medzera
while( tr.Peek()!=-1)//po koniec suboru
{
while(tr.Peek() != -1 )// po slovach
{
pismeno=tr.Read();// Nacitanie jedneho znaku
if(pismeno=='' || pismeno==oddelovac)
break;
slovo+=(char)pismeno;
}
Console.WriteLine(slovo);
slovo="";
}
}
}
//--------------------------------------------------
Príklad na stiahnutie :www.inet.sk/download/user/priklad23.2_NacitaniePoSlovach.zip
Príklad iba demonštruje, že načítanie po slovách nie je až také jednoduché ako to bolo v C/C++. Hlavne by som chcel upozorniť na funkciu Peek(), ktorá môže byť použitá na zisťovanie konca súboru. Táto funkcia len nahliadne, aký je ďalší znak, pričom sa ale pozícia čítania v súbore nezmení. Ak je súbor už na konci vráti -1.
>>Bufferovaná práca so súbormi
Buffer, čiže zásobník nám umožňuje zrýchliť prácu s veľkými súbormi, ktoré sa čítajú sekvenčne. Funguje na tomto princípe: z disku sa načíta blok za sebou idúcich dát v súbore rýchlejšie ako každý znak zvlášť.
Preto, keď začneme čítať zo súboru, najprv sa blok dát načíta do pamäti a potom pristupujeme len k týmto údajom v pamäti. Keď sa údaje z pamäti vyčerpajú, znova sa načíta nasledujúci blok údajov zo súboru. Všetko sa to deje natoľko transparentne, že sa programátor nemusí vôbec zaujímať o toto celé pozadie. Z jeho pohľadu sa načítava zo súboru každý znak samostatne.
Príklad 23.3
//--------------------------------------------------
using System;
using System.IO;
class MainClass
{
public static void Main(string[] args)
{
string bigFileName;
Console.Write(" Zadajte celu cestu k suboru:");
bigFileName=Console.ReadLine();
if (File.Exists(bigFileName) == false)
{
Console.WriteLine("Subor {0} neexistuje",bigFileName);
Console.ReadLine();
return;
}
FileStream fs = new FileStream(bigFileName,FileMode.Open,
FileAccess.Read,FileShare.None,
1000 );// v bytoch
DateTime dt1 = DateTime.Now;
while( fs.ReadByte()!=-1); //iba prazdne citanie
DateTime dt2 = DateTime.Now;
long rozdiel = (dt2.Minute-dt1.Minute)*60+ dt2.Second - dt1.Second;
Console.WriteLine("Cas [s] = {0}", rozdiel);
}
}//--------------------------------------------------
Príklad na stiahnutie : www.inet.sk/download/user/Priklad23.3_Buffer.zip
Ako vidíte, veľkosť vyrovnávacej pamäti (buffera) sa nastavuje v konštruktore FileStream() Odporúčam vám príklad vyskúšať na väčších súboroch. ja som použil súbor o veľkosti 236MB a dosiahol som tieto výsledky:
Buffer [Byt] | Čas [s]
1 000 6
1 00 13
1 0 70
Závislosť nie je lineárna a určite veľa závisí aj od nastavenia operačného systému.
>>Čo bude nabudúce?
Závisí aj od vás, čo napíšete do diskusie, ale určite pokračujem so súbormi. Chcel by som ale hlavne ukázať prácu s binárnymi súbory.
>>Predchádzajúce diely:
Programujeme v jazyku C# - Diel 22. - Súbory II .
Programujeme v jazyku C# - Diel 21. - Súbory I .
Programujeme v jazyku C# - Diel 20. – Console
Michal Čižmár
micitn@orangemail.sk