15. Fájlkezelés

Default book

A fájlkezelés során több lehetőségünk van, amelyek egymáshoz hasonlóak, de mindegyiket érdemes kicsit máskor használni.

Fájl típusok

  • Szöveges (text) fájlok
    • Ezekben a fájlokban ASCII vagy UTF-8 vagy Unicode kódolású szövegek vannak. Semmiféle szövegformázás nem értelmezhető benne.
    • A fájlok sorokból állnak és a sorok végén szabványos soremelés karakterek találhatók. Ez a C# nyelv esetén a \n karakter.
    • Ezeket a fájlokat tipikusan soronként olvassuk és írjuk.
    • A fájl sorainak nem egyforma a hossza!
  • Bináris fájlok
    • Ezeknek a fájloknak nincsen általánosítható szabványos belső szerkezetük. Minden fájltípusnak saját belső szerkezete van (JPG, EXE, PNG, stb...)
    • Ezeknek a fájloknak az olvasása és írása karakterenként, bufferenként történik, az írás és olvasás előtt pozicionálni kell a fájlon belül az írás-olvasás mutatót.

Fájlokkal való műveletek az alábbiak közül kerülhetnek ki

  • Fájl megnyitása
    • Létező fiájl megnyitása olvasásra
    • Új fájl létrehozása és megnyitása írásra
    • Létező fájl megnyitás hozzáírásra
  • A fájlon belül az írás-olvasás mutató pozicionálása
  • Egy karakter beolvasása a megnyitott fájlból
  • Egy sor beolvasása a megnyitott fájlból.
  • Fájl bezárása - Bár az operációs rendszer és a fordító mindig olyan kódot hoz létre, amelyben a megnyitott fájlok a program végetértekor bezárulnak, de elvileg ha egy fájlt már nem akarunk használni, akkor a fájlt be kell zárni.

A fájlkezeléshez a System.IO névteret kell használni.

Fájl megnyitása

Két módszer van:

FileStream fs = new FileStream("C:\\Dir1\\Dir2\\test.txt", FileMode.Open);

using System;
using System.io;
...
FileStream fs = new FileStream("C:\\Dir1\\Dir2\\test.txt", FileMode.Open);
StreamReader rs = new StreamReader(fs);

​Vagy egyszerűen

using System;
using System.io;
....
StreamReader sr = new StreamReader("C:\\Dir1\\Dir2\\test.txt");

Text fájlok kezelése - Olvasás fájlból

A továbbiakban feltételezzük, hogy van egy megnyitott sr nevű StreamReader típusú fájlunk.

A fájl tartalmát be kell olvasni. Két utasításunk van erre a célra:

  • sr.Read() - Egy karaktert olvas be a textfájlból
  • sr.ReadLine() - Egy text file egy sorát olvassa be.

Mivel egy időben egyszerre több fájlt is meg tudunk nyitnirs egy programban, ezért hivatkozni kell arra, hogy melyik fájlból olvassunk, ahogyan az alábbi példában is látszik. Az rs nevű megnyitott fájl egy sorát olvassuk be egy stringbe!

using System;
using System.io;
....
string sor;
StreamReader sr = new StreamReader("C:\\Dir1\\Dir2\\test.txt");

sor = sr.ReadLine();

Ha egy fájl tartalmát, azaz minden sorát be kell olvasni és fel kell dolgozni, akkor azt tipikusan egy ciklussal oldjuk meg. Hány sort kell beolvasnunk azt a fájl megnyitásakor nem tudjuk feltétlenül. ez egy általános probléma, így a programozási nylevben van egy olyan lehetőségünk, hogy minden fájlművelet végén lekérdezhetjük, hogy elértük-e a fájl végét.

  • sr.EndOfStream - Ennek a változónak a lekérésével megállapíthatjuk, hogy elértük-e a fájl végét. Ha elértük, akkor ennek az értéke True, ha nem értük el, akkor False

Nyilvánvalóan, ha ciklust kell használni és nem tudjuk, hogy hányszor, akkor while ciklust fogunk használni.

using System;
using System.io;
....
string sor;
StreamReader sr = new StreamReader("C:\\Dir1\\Dir2\\test.txt");

sor = sr.ReadLine();
while ( ! sr.EndOfFile ){
   .... beolvasott adatok feldolgozása....
   sor = sr.ReadLine();
}
sr.Close();

Miután beolvastuk a fájl sorqait és végére értünk a fájlnak a fájlt be kell zárnunk. Erre való az sr.Close() metódus.

Hibakezelés fájlok esetén.

Előfordulhat, hogy egy programban a beírt elérési útvonal nem található, a fájlt letörölték vagy más okból nem elérhető a fájl. Ezt a helyzetet hibakezeléssel kell orvosolni.

Olvasás szöveges fájlból - OpenFileDialog segítségével

Az alábbi összetett példában használjuk a Lista adattípust. Egy szövegfile-ból beolvassuk a sorokat és azokat betesszük egy listába.

Használjuk az OpenFileDialog objektumot, amelynek segítségével nyitunk egy párbeszédablakot, kiválaszthatjuk a megfelelő típusú fájlt (*.txt fájlok lehetnek csak), majd elkezdjük beolvasni a fájlokat.

Mielőtt elkezdjük a listába betenni az adatokat törölni kell a listát a Lista.Clear() metódussal, ráadásul a fileműveletek esetén előre nem látható dolgokkal is foglalkozni kell, ezért try{....}catch{....} részbe tesszük a beolvasott adatokat, hogyha a fájl olvasása során hiba adódna (például nem text file-t olvasunk be, mert valaki viccesen átnevezte a file kiterjesztését), akkor se feküdjön le a program.

//Az alábbi példában keverem a lista és az OpenFileDialog tudást...

using System;
using System.IO;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Lista{

.....

  void FileReadClick(object sender, EventArgs e)
  {
     string sor;
     OpenFileDialog od = new OpenFileDialog();
     od.Filter = "(Text file)|*.txt";             // Csak a txt kiterjesztásű fájlok jelenjenek meg
     if(od.ShowDialog() == DialogResult.OK)        // Megjelenítjük a filekereső ablakot
     {
       try
       {
         lista.Clear();			           // A listát töröljük
         StreamReader sr = new StreamReader(od.FileName);
         sor = sr.ReadLine();
         while (!sr.EndOfStream)                   // A file végéig olvasunk
         {
           lista.Add(sor);                         // A beolvasott sort a listába tesszük
           sor = sr.ReadLine();             
         }					
         sr.Close();
         filebe.Text ="a file-t feldolgoztuk!";
 
         //Itt kiírhatjuk a lista elemeit egy szövegdobozva;
      }
      catch
      {
         filebe.Text = "Hiba a beolvasásban! Talán nem megfelelő formátumú a file!";
      }
    }
  }
}

Írás szöveges file-ba

Ebben a példában egy lista adatait írjuk bele egy szöveges fájlba. Használjuk a SaveFileDialog objektumot.

StreamWriterrel írjuk ki a lista elemeit egy fájlba. Itt is kell try {....} catch{....} mert a fileműveleteknél sohasem biztos ...

using System;
using System.IO;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Lista{

....
  void WriteClick(object sender, EventArgs e)
  {
    SaveFileDialog od = new SaveFileDialog();
    od.Filter = "(Text file)|*.txt";
    od.Title  = "A lista mentése fájlba";
    od.ShowDialog();
    if (od.FileName != "")                        //Azt vizsgáljuk, hogy megfelelő fájlt választott-e
    {
      try
      {
        StreamWriter sw = new StreamWriter(od.FileName);  //Létrehozzuk a kimeneti fájlt
        foreach( string sor in lista)                     //Ciklussal végigmegyünk a lista elemein
        {
          sw.WriteLine(sor);			
        }
        sw.Close();                                       // A végén bezárjuk a fájlt
        filebe.Text = "'" + od.FileName + "': A file-ba beírtuk a listaelemeket!";
      }
      catch
      {
        filebe.Text = "Hiba a kiírásban!";
      }
    }
  }
}