Фајлови и директоријуми

У лекцијама које следе научићете да користите C# за рад са фајловима и директоријумима, односно за рад са Windows фајл системом. НАПОМЕНА: Пошто у програмском језику C# можемо приступити огромној библиотеци готових класа, сваки задатак може се решити на више начина, коришћењем метода и својстава из различитих класа. Не треба да вас буни ако је неко на интернету исти проблем решио другачије него што сте га ви решили. Такође, у различитим изворима, нарочито на српском језику, у употреби је пуно синонима: фајл или датотека, директоријум или фолдер, каталог, фасцикла, именик, омотница итд. У C# документацији обично се користе термини фајл и фолдер, док се у .NET документацији обично користе фајл и директоријум.

Увод

Пре него што почнемо са програмирањем, подсетићемо се првих часова информатике и лекције о организацији података на дисковима. Фајл систем дефинише како су подаци организовани на уређајима за складиштење података (HDD, SSD, CD/DVD и др.). Фајл систем треба да обезбеди податке за идентификацију фајла (име са екстензијом), податке о томе где се налази почетак и крај фајла, метаподатке о фајлу (контролне податке за проверу исправности фајла, атрибуте фајла, податке о правима приступа итд.). Поред тога, фајл систем треба да обезбеди и начин за груписање фајлова у организационе јединице, односно у директоријуме.

У Windows окружењу уређаји за складиштење података (односно логичке целине на уређајима за складиштење података) именују се словима енлгеског алфабета иза којих следи двотачка. Обично су A: и B: резервисана имена за дискове у флопи диск уређајима који се више и не користе. C: је обично први диск (или партиција на првом диску) на којем је инсталиран оперативни систем, па након тога D: може бити други диск (или друга партиција првог диска) или неки оптички уређај (CD/DVD) итд. Када прикључимо нови диск, нпр. USB флеш диск, он ће бити именован следећим слободним словом, нпр Е:.

У Windows окружењу се и даље могу користити различити фајл системи: NTFS, exFAT и FAT32. NTFS је подразумевани фајл систем за савремене рачунарске системе са Windows оперативним системима. exFAT и FAT32 су застарели и прично ограничени фајл системи – недостају им безбедносне одлике које су имплементиране у NTFS систему, а имају ограничења у погледу максималне величине партиција и максималне величине фајлова. Због тога више није могуће инсталирати оперативни систем Windows на диск са exFAT или FAT32 фајл системом. У оперативним системима Linux/UNIX и MacOS користе се други фајл системи у којима се и сама филозофија организације података разликује од ове коју ћемо обрађивати на часовима!

Ако приступимо неком именованом диску каже се да смо приступили кореном директоријуму диска, нпр. C:\ је корени директоријум C: диска. У њему се могу налазити и фајлови и директоријуми. Ако сачувамо фајл MojFajl.txt у корени директоријум C: диска, онда се тај фајл налази на локацији C:\MojFajl.txt. Ако направимо директоријум MojiPodaci у кореном директоријуму C: диска, па у њега сачувамо фајл MojFajl.txt онда се тај фајл налази на локацији C:\MojiPodaci\MojFajl.txt.

Приликом писања програма у програмској језику C# локација фајла може бити одређена на два начина: навођењем апсолутне путање или навођењем релативне путање. Апсолутна путања садржи комплетну путању до фајла (од кореног директоријума све до директоријума у којем се налази фајл) и име фајла. Релативна путања садржи путању до фајла у односу на локацију извршног фајла апликације (места где се апликација извршава) и име фајла. На пример, ако је локација извршног фајла апликације C:\Projekat1\MojaAplikacija.exe, а наведена путања до фајла којем ће апликација приступати C:\Projekat1\Tekstovi\MojFajl.txt каже се да је наведена апсолутна путања. Ако је локација извршног фајла апликације: C:\Projekat1\MojaAplikacija.exe, а наведена путања до фајла којем ће апликација приступати Tekstovi\MojFajl.txt каже се да је наведена релативна путања. Релативне путање доприносе мобилности апликације, јер се апликација са подацима које користи може лако преместити у други директоријум, на други диск или други рачунар.

Основне операције за едитовање текстуалних фајлова

Неке основне операције за рад са текстуалним фајловима могу се реализовати помоћу метода из класе File из именског простора System.IO. Више о методама из класе FILE можете пронаћи ОВДЕ.

ЗАДАТАК 1. Напишите програм за упис текста Pozdrav! у фајл MojFajl.txt. Након тога, програм треба да из фајла MojFajl.txt прочита сав текст и испише га у конзоли. Користите релативне путање.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string tekstZaUpis = "Pozdrav!";
            File.WriteAllText("MojFajl.txt", tekstZaUpis);
            string procitaniTekst = File.ReadAllText("MojFajl.txt");
            Console.WriteLine(procitaniTekst);
        }
    }
}

Метода WriteAllText креира нови фајл, уписује задати текст у фајл и затвара фајл. Ако фајл већ постоји, онда ће се његов садржај обрисати, а уписаће се задати текст. Метода ReadAllText отвара фајл, учитава цео текст из фајла у стринг и затвара фајл.

ЗАДАТАК 2. Напишите програм који у првој линији фајла уписује ваше име и презиме, у другој линији адресу ваше електронске поште и у трећој ваш број телефона. Име фајла треба бити по моделу PrezimeIme.txt, a фајл треба бити сачуван у претходно креираном директоријуму C:\III2\. Приликом навођења апсолутне путање, испред наводника користи се знак @, јер се у свакој апсолутној путањи налази бар један знак \.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] linijeZaUpis = { "Velimir Radlovacki", "velimir.radlovacki@teslavs.edu.rs", "+38113830668" };
            File.WriteAllLines(@"C:\III2\RadlovackiVelimir.txt", linijeZaUpis);
            string[] procitaneLinije = File.ReadAllLines(@"C:\III2\RadlovackiVelimir.txt");
            foreach (string linija in procitaneLinije)
                Console.WriteLine(linija);
        }
    }
}

Метода WriteAllLines креира нови фајл, уписује низ стрингова у фајл и затвара фајл. Сваки елемент низа стрингова уписује се у нову линију фајла, односно нови ред. Метода ReadAllLines отвара фајл, учитава све линије (редове) у елементе низа стрингова и затвара фајл.

ЗАДАТАК 3. У фајл који сте креирали у претходном задатку додајте вашу адресу становања, па испишите садржај целог фајла у конзоли.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string adresa = "Sterijina 40, Vrsac 26300";
            File.AppendAllText(@"C:\III2\RadlovackiVelimir.txt", adresa);
            string procitaniTekst = File.ReadAllText(@"C:\III2\RadlovackiVelimir.txt");
            Console.WriteLine(procitaniTekst);
        }
    }
}

Метода AppendAllText додаје задати текст у фајл и затвара фајл. Ако фајл не постоји биће креиран. Наравно, постоји и метода AppendAllLines која додаје низ стрингова у фајл и затвара фајл.


Основне операције за рад са фајловима и директоријумима

Неке основне операције за рад са директоријумима могу се реализовати помоћу метода из класа File, Directory и DirectoryInfo из именског простора System.IO. Више о методама из класе Directory можете пронаћи ОВДЕ, а класе DirectoryInfo ОВДЕ.

ЗАДАТАК 1. Напишите програм који ће у конзоли исписати путање до свих фајлова са екстензијом txt који се налазе у директоријуму C:\III2.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var txtFajlovi = Directory.EnumerateFiles(@"C:\III2", "*.txt");
            foreach (string fajl in txtFajlovi)
                Console.WriteLine(fajl);
        }
    }
}

Метода EnumerateFiles враћа имена фајлова са путањом која одговарају критеријуму за претрагу.

ЗАДАТАК 2. Напишите програм који ће у конзоли исписати путање до свих директоријума који се налазе у директоријуму C:\.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var direktorijumi = Directory.EnumerateDirectories(@"C:\");
            foreach (string direktorijum in direktorijumi)
                Console.WriteLine(direktorijum);
        }
    }
}

Метода EnumerateDirectories враћа имена директоријума са путањом која одговарају критеријуму за претрагу.

ЗАДАТАК 3а. Напишите програм који проверава да ли постоји директоријум C:\III2. Ако постоји, програм о томе треба да обавести корисника, а ако не постоји, програм треба да га креира.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            if (Directory.Exists(@"C:\III2"))
                Console.WriteLine(@"Direktorijum C:\III2 vec postoji!");
            else
            {
                Directory.CreateDirectory(@"C:\III2");
                Console.WriteLine(@"Direktorijum C:\III2 je uspesno kreiran!");
            }
        }
    }
}

Метода Exists одређује да ли задати директоријум постоји, а метода CreateDirectory креира задати директоријум.

ЗАДАТАК 3б. Претходни задатак решите помоћу метода из класе DirectoryInfo.

using System;
using System.IO;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo direktorijum = new DirectoryInfo(@"c:\III2");
            if (direktorijum.Exists)
                Console.WriteLine(@"Direktorijum C:\III2 vec postoji!");
            else
            {
                direktorijum.Create();
                Console.WriteLine(@"Direktorijum C:\III2 je uspesno kreiran!");
            }        
        }
    }
}

Својство Exists добија вредност на основу тога да ли директоријум постоји или не постоји, а метода Create креира директоријум.


Рад са фајловима помоћу токова података

Овакав начин рада са фајловима познат вам је из I и II разреда у програмском језику C. Ток података (енгл. stream) посматра се као низ бајтова који се линеарно крећу од тастатуре или фајла до апликације (улазни ток – енгл. input stream), односно, од апликације до екрана или фајла (излазни ток – енгл.output stream). Класа помоћу које се чита из фајла зове се StreamReader, а класа помоћу које се пише у фајл StreamWriter. Обе класе налазе се у именском простору System.IO. Да би се ток података читао из фајла, неопходно је направити нови објекат класе StreamReader позивом конструктора. Такође, да би се ток података уписао у фајл неопходно је направити нови објекат класе StreamWriter позивом конструктора.