Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

1. diel - Úvod do práce so súbormi v jazyku C ++

Vitajte u prvej lekcie kurzu tutoriálov o prácu so súbormi a prúdmi v jazyku C ++.

K čomu potrebujeme súbory?

Doteraz sme vždy pracovali len so štandardným vstupom a výstupom (teda s objektmi cout a cin). Všetky dáta sme mali uložené v pamäti RAM. To má nespornú výhodu v rýchlosti ich čítaní, avšak po ukončení aplikácie sú všetky dáta z pamäte vymazané a tým stratená. Ak našu aplikáciu spustíme znova, k dátam sa už nedostaneme (pretože už ani neexistujú). Tu prichádza na rad súbory. Do súborov si môžeme vložiť ľubovoľnú informáciu a pri ďalšom spustením aplikácie ju opäť načítať.

V C ++ je práca so súbormi súčasťou väčšieho celku, ktorý sa nazýva prúdy. Čo to sú prúdy a ako s nimi pracovať si povieme neskôr. V tejto lekcii sa pozrieme na základnú prácu so súbormi.

Základné operácie

Pre prácu so súbormi má C ++ dve API. Jedno API je v hlavičke cstdio a jedná sa o API zdedené z jazyka C. Toto API je popísané v kurze Práca so súbormi v jazyku C a nebudeme sa ním ďalej zaoberať. Čisto C ++ API pre prácu so súbormi ponúka knižnica fstream. V nej je (okrem iných tried) trieda fstream, s ktorou budeme dnes pracovať.

API je skratka pre A pplication P rogramming I nterface. To sa dá preložiť ako "rozhranie pre programovanie aplikácií" a jedná sa o súhrn funkcií a tried, ktoré môže programátor využívať. Napríklad napíšete Ak knižnicu pre sčítaní dvoch čísel, jej rozhranie bude napr. Funkcie double secti(double a, double b). Každá knižnica poskytuje nejaké rozhranie, v opačnom prípade by nebol spôsob ako s ňou pracovať. To, že môžeme vypisovať do konzoly ako cout << neco, je opäť len API, ktoré poskytuje objekt cout (alebo všeobecnejšie štandardná knižnica).

Otvorenie súboru pre zápis

Súbor najskôr musíme otvoriť (či vytvoriť, ak neexistuje). To vykonávame konstruktoru objektu, ktorý prijíma názov súboru ako parameter. Ak chceme súbor aj vytvoriť, odovzdáme ako druhý parameter konstruktoru hodnotu ios::out. Potom zo súboru môžeme čítať alebo do neho zapisovať. Nasleduje uvoľnenie prostriedkov pomocou metódy close().

Ukážme si prvý príklad, ktorý otvorí súbor pre zápis:

fstream soubor("zapis.txt", ios::out);

// operace se souborem

//nemusi byt volano, bude zavolano po destruovani objektu
soubor.close();

Ak by sme objekt neuzavreli, súbor zostane v držaní aplikácie. V takom prípade vám operačný systém neumožní so súborom manipulovať (napríklad ho zmazať), dokiaľ nie je súbor uvoľnený. Jedná sa o klasickú hlášku "Súbor sa nedá zmazať, pretože je používaný iným procesom". Treba podotknúť, že trieda fstream vykonáva uzavretie automaticky v destruktor, metódu close() je teda nutné volať len pre objekty, ktorých platnosť je dlhšia ako je ich použitie (napríklad na začiatku metódy main()).

Zápis do súboru

Vieme otvoriť už existujúci súbor pre zápis. A ako že do neho vlastne zapisovať? Prekvapivo rovnako, ako sme to robili s objektom cout. Objekt cout je totiž podobne ako trieda fstream iba prúd. Poďme teda vypísať do súboru text "Hello World":

fstream soubor("zapis.txt", ios::out);

soubor << "Hello World" << endl;

//nemusi byt volano, bude zavolano po destruovani objektu
soubor.close();

A ak chceme sa súboru niečo prečítať? Opäť použijeme to, čo už poznáme. Čítanie prebieha rovnako ako pri objekte cin, ktorý je (prekvapivo) opäť iba prúd. Načítate text, ktorý sme do súboru zapísali výšky:

fstream soubor("zapis.txt");

string slovo;
soubor >> slovo;
cout << slovo << endl;

//nemusi byt volano, bude zavolano po destruovani objektu
soubor.close();

Teraz už vieme základné operácie. To ale nie je všetko. Prúdy toho vie oveľa viac a teraz si predstavíme ich základné metódy.

Neformátovaný vstup a výstup

Všetko, čo sme zatiaľ vykonávali, sme robili na tzv. Formátovanom vstupu, resp. výstupu. Prečo hovoríme o formátovanom? Ak sme chceli vypísať napríklad číslo, len sme do cout poslali int a cout sa už postaral o správny prevod čísla na text. Inými slovami nami odovzdaná dáta naformátovali do čitateľnej podoby. Niekedy kvôli výkonu chceme formátovanie preskočiť a vypísať iba text. O to sa stará práve neformátovaný vstup, resp. výstup.

Neformátovaný výstup

Pre výstup sú to dve metódy, put() a write(). Tá prvá odovzdá na výstup len jeden znak, zatiaľ čo metóda write() vypíše pole. Prečo by sme chceli používať neformátovaný výstup? Pretože je rýchlejší ako výstup formátovaný. Pre neformátovaný výstup neprebieha žiadna konverzia, žiadna kontrola, obsah poľa je iba skopírovaný.

Neformátovaný vstup

Pre neformátovaný vstup je metód viac. Základom je metóda get(), ktorá zo vstupu odoberie jeden znak. Existuje aj preťaženie, ktoré zo vstupu odoberie znakov niekoľko.

  • int get() vráti znak zo vstupu.
  • istream& get (char& c) vráti znak zo vstupu argumentom.
  • istream& get (char* s, streamsize n) vráti až n-1 znakov zo vstupu a uloží ich do poľa s. Funkcia skončí po prečítaní n-1 znakov alebo po výskyte znaku \n na vstupe (ten vo výstupe zostáva). Na koniec poľa sa automaticky pridá znak \0 a jedná sa teda o plnohodnotný C-like reťazec (preto číta max n-1 znakov).
  • istream& get (char* s, streamsize n, char delim) rovnaký ako predchádzajúci prípad, iba možno namiesto ukončovacieho symbolu \n zvoliť čokoľvek iného.
  • istream& get (streambuf& sb) prečíta vstup až po znak \n a vloží ho do streambufferu (viď. ďalší lekcie).
  • istream& get (streambuf& sb, char delim) prečíta vstup až po znak delim a vloží ho do streambuferu (viď. ďalší lekcie).

Vstup má ďalej metódy read() a getline(), ktoré fungujú takmer rovnako ako tretí prípad metódy get(). Metóda read() len prečíta n znakov alebo zlyhá (nepridáva \0 znak). Metóda getline() prečíta maximálne n-1 znakov, pridá \0 symbol a ukončovacie symbol delim odstráni zo vstupu, ak na neho narazila. K tomu, ako vstup môže zlyhať, sa dostaneme niekedy inokedy.

Nahliadanie

Okrem samotného čítania môžete na znaky iba nazerať, a to metódou peek(). Tá vráti ďalší znak zo vstupu, ale neodstráni ho (takže zostane pre ďalšie čítanie k dispozícii).

Pridávanie

Na výstup môžete dokonca aj znaky pridávať, a to metódou putback(). Tá vloží jeden znak do fronty na čítanie. To sa samozrejme neprejaví v konzole (text, ktorý užívateľ napísal, tam zostane), ale pri ďalšom čítaní bude znak prečítaný.

Ignorovanie

Nakoniec tu máme metódy pre ignorovanie vstupu, tj. Metódu ignore(). Tá je deklarovaná ako istream& ignore (streamsize n = 1, int delim = EOF). Parameter n udáva počet znakov na odstránenie (-1 znamená bez limitu) a delim definuje znak, kde sa má metóda zastaviť. Konštanta EOF označuje koniec súboru (taktiež bude prebrané ďalej).

Nasledujúci program demonštruje základné neformátované operácie:

//{
fstream zapis("soubor.txt", ios::out);
zapis.write("Hello World", 11);
zapis.put('!');
zapis.put('?');
zapis.close();
//}

fstream cteni("soubor.txt", ios::in);
cout << "Dalsi znak: " << (char)cteni.peek() << endl;
char prvni = (char)cteni.get();
char druhy = (char)cteni.get();
cout << "Po znaku " << prvni << " je znak " << druhy << endl;
char zbytekHello[4];
cteni.get(zbytekHello, 4, ' ');
cout << "Zbytek slova je " << zbytekHello << endl;
cteni.ignore(999, 'l');
cout << "Dalsi znak po prvnim ignorovani: " << (char)cteni.peek() << endl;
cteni.ignore(1);
char zbytekRadku[3];
cteni.getline(zbytekRadku, 3);
cout << "Po ignorovani je zbytek radku " << zbytekRadku << endl;
cteni.close();

Všimnite si explicitného uzatvorenie prvého súboru. Pokiaľ by prvý objekt nebol uzavretý, druhý by z neho nemohol čítať, pretože súbor môže byť otvorený vždy iba raz. Avšak ak by bol prvý blok kódu uzavretý do zložených zátvoriek, potom sa na ich konci zavolá deštruktor objektu zapis a tak môžeme volanie metódy close() vynechať.

Kompletné výklad, čo druhý parameter konstruktoru ios::out robí, si necháme na niekedy inokedy.

Tým máme základy za sebou. Nabudúce, v lekcii Typy súborov a správne umiestnenie súborov v C ++ , sa pozrieme na rôzne typy súborov a ako s nimi nakladať.


 

Všetky články v sekcii
Súbory a práca s nimi v C ++
Preskočiť článok
(neodporúčame)
Typy súborov a správne umiestnenie súborov v C ++
Článok pre vás napísal Patrik Valkovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity