A fájl I/O működése C++-ban majdnem megegyezik a normál I/O-éval (de néhány árnyalattal).

Fájl I/O osztályok

Van három fő fájl I/O osztály a C++ nyelven:

folyamon kívül(az osztály gyermeke );

fstream(az iostream osztály gyermeke).

Ezekkel az osztályokkal egyirányú fájlbevitelt, egyirányú fájlkimenetet és kétirányú fájl I/O-t hajthat végre. Használatukhoz csak csatlakoztatni kell az fstreamet.

A cout, cin, cerr és clog folyamokkal ellentétben, amelyek azonnal használhatók, a fájlfolyamokat a programozónak kifejezetten be kell állítania. Azaz egy fájl olvasásra és/vagy írásra való megnyitásához létre kell hozni a megfelelő fájl I/O osztályú objektumot, paraméterként megadva a fájl nevét. Ezután a beillesztési operátorokkal (<<) или извлечения (>>), adatokat írhat egy fájlba, vagy elolvashatja a fájl tartalmát. Ezt követően a végső - be kell zárnia a fájlt: kifejezetten hívja close() metódus vagy csak hagyja, hogy a fájl I/O változója kikerüljön a hatókörből (a fájl I/O osztálya automatikusan bezárja azt a fájlt helyettünk).

Fájl kimenet

Az ofstream osztályt fájlba írásra használják. Például:

#beleértve #beleértve #beleértve // az exit() int main() használatához ( namespace std használatával; // az ofstream az adatok fájlba írására szolgál // Fájl létrehozása SomeText.txt ofstream outf("SomeText.txt"); // Ha tudjuk 'ne nyissa meg ezt a fájlt, hogy adatokat írjon az if (!outf) fájlba ( // Ezután nyomtasson egy hibaüzenetet, és futtassa az exit() cerr-t<< "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } // Записываем в файл следующие две строчки outf << "See line #1!" << endl; outf << "See line #2!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#beleértve

#beleértve

#beleértve // az exit()

int main()

névtér használata std ;

Az // ofstream az adatok fájlba írására szolgál

// SomeText.txt fájl létrehozása

ofstream outf("SomeText.txt" ) ;

// Ha nem tudjuk megnyitni ezt a fájlt, hogy adatokat írjunk bele

if(!outf)

// Ezután nyomtasson ki egy hibaüzenetet, és futtassa az exit()

cerr<< << endl ;

kilépés(1) ;

// Írja be a következő két sort a fájlba

outf<< "See line #1!" << endl ;

outf<< "See line #2!" << endl ;

return 0 ;

// Amikor az outf kikerül a hatókörből, az ofstream osztály destruktora automatikusan bezárja a fájlunkat

Ha belenézel a projektkönyvtáradba ( RMB a lapon a Visual Studio .cpp-fájljának nevével > "Tartalmazó mappa megnyitása"), megjelenik egy SomeText.txt nevű fájl, amely a következő sorokat tartalmazza:

Lásd az 1. sort!
Lásd a 2. sort!

Felhívjuk figyelmét, hogy mi is használhatjuk put() metódus hogy egy karaktert írjunk egy fájlba.

Fájlbevitel

#beleértve #beleértve #beleértve #beleértve // az exit() int main() használatához ( namespace std használatával; // az ifstream a fájl tartalmának olvasására szolgál // Próbáld meg beolvasni a SomeText.txt fájl tartalmát ifstream inf("SomeText.txt") ; // Ha nem tudjuk megnyitni ezt a fájlt a tartalmának olvasásához if (!inf) ( cerr<< "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть данные, которые мы можем прочитать while (inf) { // То перемещаем эти данные в строку, которую затем выводим на экран string strInput; inf >> strInput; cout<< strInput << endl; } return 0; }

#beleértve

#beleértve

#beleértve

#beleértve // az exit()

int main()

névtér használata std ;

// az ifstream a fájl tartalmának olvasására szolgál

// Ha nem tudjuk megnyitni ezt a fájlt a tartalmának elolvasásához

if(!inf)

// Ezután nyomtassa ki a következő hibaüzenetet, és futtassa az exit()

cerr<< << endl ;

kilépés(1) ;

// Amíg van adat, olvasni tudunk

miközben (inf)

// Ezután ezeket az adatokat áthelyezzük egy karakterláncba, amit aztán megjelenítünk a képernyőn

string strInput ;

inf >> strInput ;

cout<< strInput << endl ;

return 0 ;

// Amikor az inf kikerül a hatókörből, az ifstream osztály destruktora automatikusan bezárja a fájlunkat

Lát
vonal
#1!
Lát
vonal
#2!

Hmm, nem egészen ezt akartuk. Amint azt az előző leckékből már tudjuk, az extrakciós operátor "formázott adatokkal" dolgozik, pl. figyelmen kívül hagy minden szóközt, tabulátort és újsort. Ahhoz, hogy az összes tartalmat úgy olvassuk el, ahogy van, anélkül, hogy részekre bontjuk (mint a fenti példában), használnunk kell getline() metódus:

#beleértve #beleértve #beleértve #beleértve // az exit() int main() használatához ( az std névtér használatával; // az ifstream a fájlok tartalmának olvasására szolgál // Megpróbáljuk beolvasni a SomeText.txt fájl tartalmát ifstream inf("SomeText.txt") ; // Ha nem tudunk megnyitni egy fájlt a tartalmának elolvasásához if (!inf) ( // Ezután nyomtassa ki a következő hibaüzenetet, és lépjen ki a cerr-ből<< "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть, что читать while (inf) { // То перемещаем то, что можем прочитать, в строку, а затем выводим эту строку на экран string strInput; getline(inf, strInput); cout << strInput << endl; } return 0; // Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл }

#beleértve

#beleértve

#beleértve

#beleértve // az exit()

int main()

névtér használata std ;

// az ifstream a fájlok tartalmának olvasására szolgál

ifstream inf("SomeText.txt" ) ;

// Ha nem tudjuk megnyitni a fájlt a tartalmának elolvasásához

if(!inf)

// Ezután nyomtassa ki a következő hibaüzenetet, és futtassa az exit()

cerr<< "Ó, ó, a SomeText.txt fájlt nem sikerült megnyitni olvasásra!"<< endl ;

kilépés(1) ;

miközben (inf)

string strInput ;

getline (inf , strInput ) ;

cout<< strInput << endl ;

return 0 ;

// Amikor az inf kikerül a hatókörből, az ifstream osztály destruktora automatikusan bezárja a fájlunkat

A fenti program futtatásának eredménye:

pufferelt kimenet

A C++ kimenete pufferelhető. Ez azt jelenti, hogy minden, ami a fájlfolyamba kerül, nem írható azonnal lemezre (egy adott fájlba). Ez elsősorban teljesítmény okokból történik. Amikor a pufferadatokat lemezre írják, ezt hívják a puffer törlése. A puffer törlésének egyik módja a fájl bezárása. Ebben az esetben a puffer teljes tartalma lemezre kerül, majd a fájl bezárásra kerül.

A kimeneti pufferelés általában nem jelent problémát, de bizonyos körülmények között problémákat okozhat az óvatlan kezdőknek. Például, amikor az adatok a pufferben vannak tárolva, és a program idő előtt leállítja a végrehajtását (akár összeomlás következtében, akár hívásával). Ilyen esetekben a fájl I/O osztálydestruktorok nem kerülnek végrehajtásra, a fájlok soha nem záródnak be, a pufferek nem kerülnek kiürítésre, és az adataink örökre elvesznek. Ezért célszerű explicit módon bezárni minden nyitott fájlt az exit() hívása előtt.

A puffert manuálisan is törölheti ostream::flush() metódus vagy elküldéssel std::flush a kimeneti adatfolyamhoz. Ezen módszerek bármelyike ​​hasznos lehet annak biztosítására, hogy a program összeomlása esetén a puffer tartalma azonnal a lemezre kerüljön.

Érdekes árnyalat: Mert std::endl; törli a kimeneti adatfolyamot is, akkor annak túlzott használata (ami szükségtelen puffer-öblítéseket eredményez) befolyásolhatja a program teljesítményét (mert a puffer-öblítés bizonyos esetekben költséges lehet). Emiatt a teljesítménytudatos programozók gyakran \n-t használnak az std::endl helyett, hogy újsort szúrjanak be a kimeneti adatfolyamba, hogy elkerüljék a szükségtelen puffer-öblítést.

Fájl megnyitási módok

Mi történik, ha egy már létező fájlba próbálunk adatokat írni? A fenti program ismételt futtatása (a legelső) azt mutatja, hogy a program ismételt futtatásakor az eredeti fájl teljesen felülíródik. De mi van akkor, ha adatokat kell hozzáadnunk a fájl végéhez? Kiderült, hogy a fájlfolyamnak egy opcionális második paramétere van, amely lehetővé teszi, hogy megmondja a programozónak, hogyan nyissa meg a fájlt. Mivel ez a paraméter, akkor át következő zászlókat(amelyek az ios osztályba tartoznak):

kb- megnyitja a fájlt hozzáfűzés módban;

evett- olvasás/írás előtt a fájl végére megy;

bináris- bináris módban nyitja meg a fájlt (szöveg mód helyett);

ban ben- megnyitja a fájlt olvasási módban (alapértelmezett ifstream);

ki- írási módban nyitja meg a fájlt (alapértelmezett az offstream);

trunc- törli a fájlt, ha már létezik.

A használatával egyszerre több zászlót is megadhat.

az ifstream alapértelmezés szerint ios::in módban működik;

az ofstream alapértelmezés szerint ios::out módban működik;

Az fstream alapértelmezés szerint ios::in VAGY ios::out módban fut, ami azt jelenti, hogy elolvashatja egy fájl tartalmát, vagy adatokat írhat egy fájlba.

Most írjunk egy programot, amely két sort fog hozzáadni a korábban létrehozott SomeText.txt fájlhoz:

#beleértve #beleértve // az exit() #include használatához int main() ( namespace std használatával; // Ha átadjuk az ios:app jelzőt az fstream-nek, hogy hozzá fogjuk adni az adatainkat a fájl már meglévő adataihoz, // nem fogjuk felülírni a fájlt. t kell átadni az ios::out jelzőt , // mivel az ofstream alapértelmezett értéke ios::out ofstream outf("SomeText.txt", ios::app); // Ha nem tudunk megnyitni egy fájlt adatíráshoz, ha (!outf) ( // Ezután adja ki a következő hibaüzenetet, és exit() cerr<< "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } outf << "See line #3!" << endl; outf << "See line #4!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#beleértve

#beleértve // az exit()

#beleértve

int main()

névtér használata std ;

// Az ios:app jelző átadása az fstream számára, hogy adatainkat hozzáadjuk a fájl már meglévő adataihoz,

// nem fogjuk felülírni a fájlt. Nem kell átadnunk az ios::out jelzőt,

// mert az ofstream alapértelmezés szerint az ios::out mód

ofstream outf("SomeText.txt" , ios::app ) ;

// Ha nem tudjuk megnyitni a fájlt adatok írásához

if(!outf)

// Ezután nyomtassa ki a következő hibaüzenetet, és futtassa az exit()

cerr<< "Ó, a SomeText.txt nem nyitható meg íráshoz!"<< endl ;

kilépés(1) ;

A által kifejlesztett I/O mechanizmus nem felel meg a ma általánosan elfogadott objektum-orientált programozási stílusnak, emellett aktívan alkalmazza a pointer műveleteket is, amelyek a modern biztonságos kódvégrehajtási környezetekben potenciálisan nem biztonságosnak számítanak. Az alkalmazásfejlesztés alternatívája a C++ nyelvi szabvány által biztosított szabványos I/O osztály mechanizmus.

Fájlok megnyitása

A leggyakrabban használt osztályok az ifstream olvasáshoz, az ofstream az íráshoz és az fstream osztályok a fájlok módosításához.

Az összes szálas I/O osztály közvetve a közös ős ios-ból származik, teljes mértékben örökli annak funkcionalitását. Például az open_mode felsorolt ​​adattag a fájl megnyitási módját határozza meg, amely a következőképpen van definiálva:

Enum open_mode ( app, binary, in, out, trunc, ate );

Az alábbiakban felsoroljuk a zászlók lehetséges értékeit és célját.

Például egy test.txt nevű fájl megnyitásához bináris adatok olvasásához a következőket kell írnia:

ifstream fájl; file.open("teszt.txt", ios::in | ios::bináris);

A logikai VAGY operátor (|) lehetővé teszi a mód összeállítását a jelzők bármilyen kombinációjával. Annak érdekében, hogy egy fájl írással történő megnyitásakor véletlenül se írjon felül egy azonos nevű fájlt, a következő űrlapot kell használnia:

offstream fájl; file.open("teszt.txt", ios::out | ios::app);

Feltételezzük, hogy a megfelelő fejlécfájl csatlakozik a projekthez:

#beleértve

A konstrukció segítségével ellenőrizheti, hogy a fájl sikeresen megnyílt-e

If (!file) ( // Fájlmegnyitási hiba kezelése )

Befoglalás és kivonás operátorok

Felülbírálva a fájlkezelési osztályokban operátort tartalmaz (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

Fájl<< "Это строка текста";

Írhat szöveges karakterláncot részekre is:

Fájl<< "Это " << "строка " << "текста";

Az endl utasítás a sor bemenetét kocsi visszatéréssel fejezi be:

Fájl<< "Это строка текста" << endl;

Az include operátor használatával könnyen beírható a változók vagy tömbelemek értéke egy fájlba:

Offstream fájl ("Temp.txt"); char buff = "A szövegtömb változókat tartalmaz"; int vx = 100; float pi = 3,14159; fájlt<< buff << endl << vx << endl << pi << endl;

A kódvégrehajtás eredményeként a Temp.txt szövegfájl három sora jön létre:

A szövegtömb 100 3.14159 változót tartalmaz

Vegye figyelembe, hogy a numerikus értékek szöveges karakterláncokként vannak beírva a fájlba, nem pedig bináris értékekként.

kivonat operátor(>>) az ellenkezőjét teszi. Úgy tűnik, hogy a korábban írt Temp.txt fájlból a karakterek kinyeréséhez a következő kódot kell írnia:

ifstream fájl("Temp.txt"); char buff; intvx; floatpi; fájl >> buff >> vx >> pi;

A kivonatolási operátor azonban megáll az első határolónál (szóköz, tabulátor vagy újsor), amellyel találkozik. Így a "Szöveg tömb változókat tartalmaz" mondat elemzésekor csak a "Szöveg" szó kerül beírásra a tömb buffba, a szóköz figyelmen kívül marad, és a "tömb" szó lesz a vx egész változó és a kód értéke. a végrehajtás „szégyenszemre megy” az adatstruktúra elkerülhetetlen megsértésével. Ezután, amikor az ifstream osztályról beszélünk, megmutatjuk, hogyan kell helyesen megszervezni a fájl olvasását az előző példából.

ifstream osztály: fájlok olvasása

Ahogy a neve is sugallja, az ifstream osztályt fájlfolyam bevitelére tervezték. Az alábbiakban felsoroljuk az osztály főbb metódusait. Legtöbbjük az istream osztályból öröklődött, és túlterhelt a szülői funkciókkal. Például a get függvény a hívási paramétertől függően nem csak egy karaktert, hanem egy karakterblokkot is képes olvasni.

Most már világos, hogyan kell módosítania az előző példát, hogy az adatkinyerési operátor használata a várt eredményt adja:

ifstream fájl("Temp.txt"); char buff; intvx; floatpi; file.getline(buff, sizeof(buff)); fájl >> vx >> pi:

A getline metódus beolvassa a fájl első sorát a végéig, a >> operátor pedig értékeket rendel a változókhoz.

A következő példa az adatok szöveges fájlhoz való hozzáadását, majd a teljes fájl beolvasását mutatja be. A while (1) ciklust a while(!file2.eof()) helyett használjuk a cikkben tárgyalt okokból.

#beleértve #beleértve névtér használata std; int main() ( ofstream fájl; file.open("teszt.txt",ios::out|ios::app); if (!file) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >>a; if (file2.eof()) break; cout<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

A következő példa végigfut a test.txt fájl sorain, és megjeleníti azokat a konzolon.

#beleértve #beleértve névtér használata std; int main() ( ifstream fájl; // stream objektumfájl létrehozása file.open("teszt.txt"); // fájl megnyitása olvasásra if (!file) return 1; // visszatérés hiba megnyitásakor char str; / / static line buffer // Sorok olvasása és megjelenítése ciklusban, amíg eof while (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Ez a kód a Windows operációs rendszer alatt attól is függ, hogy a fájl utolsó sorában van-e újsor karakter, megbízhatóbb lenne ezt megtenni:

While (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }

A nyitás és bezárás metódusainak kifejezett hívása nem kötelező. Valójában a konstruktor argumentummal történő meghívása lehetővé teszi a fájl azonnali megnyitását, a fájlfolyam objektum létrehozásának pillanatában:

ifstream fájl("teszt.txt");

A bezárás helyett használhatjuk a delete operátort, amely automatikusan meghívja a fájlobjektum destruktorát és bezárja a fájlt. A while cikluskód megfelelő fájlvégi ellenőrzést biztosít.

ofstream osztály: fájlok írása

Az ofstream osztályt úgy tervezték, hogy adatokat adjon ki egy fájlfolyamból. Az alábbiakban felsoroljuk ennek az osztálynak a főbb módszereit.

A korábban leírt include operátor kényelmes a szöveges fájlba való írás megszervezéséhez:

Offstream fájl("temp.txt"); if (!file) return; for (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Binárisok

Elvileg a bináris adatokat úgy szolgálják ki, mint a szöveges adatokat. A különbség az, hogy ha a bináris adatok egy bizonyos logikai struktúrába vannak írva, akkor azokat a fájlból egy azonos szerkezeti típusú változóba kell beolvasni.

Az írási és olvasási metódusok első paraméterének (az írási/olvasási blokk címének) karaktermutató char * típusúnak kell lennie, ezért a void * struktúra címének típusát kifejezetten át kell alakítani. A második paraméter azt határozza meg, hogy a fájl bináris blokkjai állandó bájtmérettel rendelkeznek, függetlenül a tényleges rekordhossztól. A következő függelék példát mutat arra, hogyan lehet adatokat létrehozni és megjeleníteni egy egyszerű notebookban. A fájl rekordjai ezután sorban olvashatók, és megjelennek a konzolon.

#beleértve #beleértve #beleértve névtér használata std; struct Notes ( // a notebook adatszerkezete char Név; // teljes név char Telefon; // phone int Életkor; // életkor ); int main() ( setlocale(LC_ALL, "orosz"); Notes Note1= ("Grozny Ioann Vasilyevich", "nincs telepítve", 60 ); Notes Note2= ("Godunov Boris Fedorovich", "095-111-2233", 30 ); Notes Note3= ( "Peter Romanov ", "812-333-2211 ", 20 ); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof ( Notes)); // 1. blokk ofile.write((char*)&Note2, sizeof(Notes)); // 2. blokk ofile.write((char*)&Note3, sizeof(Notes)); / / 3. blokk ofile. close(); // bezárja az írott fájlt ifstream ifile("Notebook.dat", ios::binary); Megjegyzések; // strukturált változó char str; // statikus string puffer // Sorok olvasása és megjelenítése ciklusban, amíg eof while (!file.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tBody: %s\tAge: %d" , Note.Name, Note. telefon, jegyzet.életkor); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

A kód végrehajtása eredményeként három, egyenként 80 bájtos blokkból egy Notebook.dat bináris fájl jön létre (feltételezve, hogy a karakterek egybájtosak). Természetesen más streamelési módszereket is használhat, és bármilyen műveletet végrehajthat egy adott adatstruktúra mezőin.

fstream osztály: véletlenszerű fájl hozzáférés

Tegyük fel, hogy a füzetünkben 100 bejegyzés gyűlt össze, és az 50-et akarjuk megszámolni. Természetesen lehet ciklust szervezni, és az összes rekordot elolvasni az elsőtől az adottig. Nyilvánvalóan célzottabb megoldás, ha a pos fájl pozíciómutatóját közvetlenül az 50-es bejegyzésre állítjuk, és elolvassuk:

ifstream ifile("Notebook.dat", ios::bináris); int poz = 49 * sizeof(Notes); ifile seek(pos); // az 50. bejegyzés keresése Megjegyzések Megjegyzés; //Notes - a fent leírt "rekord" szerkezet ifile.read((char*)&Note, sizeof(Notes));

Az ilyen keresési műveletek akkor hatékonyak, ha a fájl ismert és állandó méretű rekordokból áll. Egy tetszőleges bejegyzés tartalmának lecseréléséhez meg kell nyitnia a kimeneti adatfolyamot módosítás módban:

Ofstream ofile("Notebook.dat", ios::bináris | ios::ate); int poz = 49 * sizeof(Notes); ofile seekp(pos); // az 50. hang keresése Notes50 = ("Jelcin Borisz Nyikolajevics", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Notes)); // csere

Ha nem adjuk meg az ios::ate (vagy ios::app) jelzőt, akkor a Notebook.dat bináris fájl megnyitásakor a korábbi tartalma törlődik!

Végül lehetőség van egy fájl egyidejű megnyitására olvasásra/írásra, olyan metódusokkal, amelyeket az fstream streaming osztály örökölt az elődjeitől. Mivel az fstream osztály az istreamből és az ostreamből származik (az ifstream és az ofstream szülőjei), az összes korábban említett metódus elérhetővé válik az alkalmazás számára.

A következő példa felcseréli a Notebook.dat fájl első és harmadik bejegyzését.

#beleértve #beleértve #beleértve névtér használata std; struct Jegyzetek ( char Név; char Telefon; int Életkor; ); int main() ( setlocale(LC_ALL, "orosz"); Notes Note1, Note3; // Fájl megnyitása az egyidejű olvasáshoz/íráshoz fstream file("Notebook.dat", ios::binary | ios::in | ios:: out); file.seekg(2 * sizeof(Notes)); // Note3 keresése és olvasása file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // Note1 keresése és olvasása file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Note1<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

Az ios::in és ios::out jelzőket meg kell adni a fájlobjektum konstruktorában, hogy lehetővé tegyék az egyidejű olvasási és írási műveleteket. A kód végrehajtásának eredményeként a Notebook.dat bináris fájl első és harmadik rekordja felcserélődik.

További példák is vannak a témában.

A legtöbb számítógépes program fájlokkal működik, ezért szükség van fájlok létrehozására, törlésére, írására, olvasására, megnyitására. Mi az a fájl? A fájl egy elnevezett bájtok gyűjteménye, amely valamilyen tárolóeszközön tárolható. Nos, most már világos, hogy a fájl egy bizonyos bájtsorozat, amelynek saját egyedi neve van, például egy .txt fájl. Az azonos nevű fájlok nem lehetnek ugyanabban a könyvtárban. A fájlnév nem csak a neve, hanem egy kiterjesztése is, például: file.txt és file.dat különböző fájlok, bár ugyanaz a név. Létezik olyan, hogy a fájlok teljes neve – ez a fájlnévvel ellátott fájlkönyvtár teljes címe, például: D:\docs\file.txt . Fontos megérteni ezeket az alapfogalmakat, különben nehéz lesz a fájlokkal dolgozni.

A fájlokkal való munkavégzéshez tartalmaznia kell egy fejlécfájlt . NÁL NÉL Számos osztály van definiálva és fejlécfájl is szerepel benne fájlbevitel és fájl kimenet.

A fájl I/O hasonló a szabványos I/O-hoz, az egyetlen különbség az, hogy az I/O nem a képernyőre, hanem egy fájlra történik. Ha a szabványos eszközök be-/kimenete a cin és cout objektumokkal történik, akkor a fájl I/O rendszerezéséhez elegendő saját objektumokat létrehozni, amelyek a cin és cout operátorokhoz hasonlóan használhatók.

Például létre kell hozni egy szöveges fájlt, és bele kell írni a Fájlok kezelése C++ nyelven sort. Ehhez a következő lépéseket kell végrehajtania:

  1. hozzon létre egy osztály ofstream objektumot ;
  2. osztályobjektumot társítani az írandó fájlhoz;
  3. írjon egy sort egy fájlba;
  4. zárja be a fájlt.

Miért szükséges az ofstream osztály objektumát létrehozni, és nem az ifstream osztályt? Mert fájlba kell írni, és ha egy fájlból adatokat kell olvasni, akkor az ifstream osztály objektuma jön létre.

// objektum létrehozása az ofstream fájlba írandó /*objektumnév*/; // class ofstream objektuma

Nevezzük az objektumot foutnak, a következő történik:

Offstream fout;

Miért van szükségünk tárgyra? Az objektum szükséges ahhoz, hogy a fájlba írni tudjon. Az objektumot már létrehozták, de nincs hozzárendelve ahhoz a fájlhoz, amelybe a karakterláncot írni kell.

fout.open("cppstudio.txt"); // objektum társítása fájlhoz

A dot műveleten keresztül jutunk hozzá az open() osztály metódusához, melynek zárójelében a fájl nevét adjuk meg. A megadott fájl az aktuális könyvtárban jön létre a programmal. Ha létezik azonos nevű fájl, akkor a meglévő fájl helyére új kerül. Tehát a fájl nyitva van, be kell írnia a kívánt sort. Ez így történik:

Fout<< "Работа с файлами в С++"; // запись строки в файл

A cast to stream műveletet a fout objektummal együtt használva a File Handling karakterlánc C++ nyelven egy fájlba íródik. Mivel a fájl tartalmát már nem kell módosítani, ezért be kell zárni, vagyis el kell választani az objektumot a fájltól.

fout.close(); // zárja be a fájlt

Ennek eredményeként létrejött egy fájl a Fájlok kezelése C++ nyelven sorral.

Az 1. és 2. lépés kombinálható, azaz egy sorban hozzon létre egy objektumot és társítsa egy fájlhoz. Ez így történik:

Offstream fout("cppstudio.txt"); // hozzon létre egy objektumot az ofstream osztályból, és társítsa azt a cppstudio.txt fájlhoz

Kombináljuk az összes kódot, és kapjuk a következő programot.

// file.cpp: a konzolalkalmazás belépési pontját határozza meg. #include "stdafx.h" #include névtér használata std; int main(int argc, char* argv) ( ofstream fout("cppstudio.txt"); // hozzon létre egy objektumot az ofstream osztályból íráshoz, és társítsa azt a cppstudio.txt fout fájlhoz<< "Работа с файлами в С++"; // запись строки в файл fout.close(); // закрываем файл system("pause"); return 0; }

Továbbra is ellenőrizni kell a program megfelelő működését, és ehhez megnyitjuk a fájlt cppstudio.txt és nézd meg a tartalmát, annak kell lennie - Fájlokkal való munkavégzés C++ nyelven.

  1. hozzon létre egy objektumot az ifstream osztályból, és társítsa azt az olvasandó fájlhoz;
  2. fájl olvasása;
  3. zárja be a fájlt.
// file_read.cpp: meghatározza a konzolalkalmazás belépési pontját. #include "stdafx.h" #include #beleértve névtér használata std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // a cirill ábécé helyes megjelenítése char buff; // az ifstream fájlból kiolvasott szöveg köztes tároló puffere fin("cppstudio.txt "); // fájl megnyitása a fin >> olvasásához<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку system("pause"); return 0; }

A program két módot mutat be a fájlból való olvasásra, az első az átvitel a folyamba művelet, a második a funkció használata getline() . Az első esetben csak az első szó, a második esetben pedig egy 50 karakteres karakterlánc kerül beolvasásra. Mivel azonban kevesebb, mint 50 karakter maradt a fájlban, a karakterek beolvasása az utolsóig bezárólag történik. Vegye figyelembe, hogy másodszori olvasás (17. sor) az első szó után folytatódott, és nem az elejétől, mivel az első szót beolvasták14. sor. A program eredménye az 1. ábrán látható.

Fájlok kezelése C++ nyelven A folytatáshoz nyomja meg bármelyik billentyűt. . .

1. ábra - Fájlok kezelése C++ nyelven

A program megfelelően működött, de ez nem mindig van így, még akkor sem, ha minden rendben van a kóddal. Például egy nem létező fájl nevét adták át a programnak, vagy hiba történt a névben. Akkor mit? Ebben az esetben semmi sem fog történni. A fájl nem található, ami azt jelenti, hogy nem lehet elolvasni. Ezért a fordító figyelmen kívül hagyja azokat a sorokat, ahol a fájlt manipulálják. Ennek eredményeként a program megfelelően kilép, de semmi sem jelenik meg a képernyőn. Úgy tűnik, hogy ez egy teljesen normális reakció egy ilyen helyzetre. De egy egyszerű felhasználó nem fogja megérteni, mi a probléma, és miért nem jelenik meg a fájl egy sora a képernyőn. Tehát, hogy minden nagyon világos legyen, a C++ biztosít egy ilyen függvényt - is_open() , amely egész értékeket ad vissza: 1 - ha a fájl sikeresen megnyílt, 0 - ha a fájl nem lett megnyitva. Véglegesítsük a programot a fájl megnyitásával úgy, hogy ha a fájlt nem nyitjuk meg, akkor egy megfelelő üzenet jelenjen meg.

// file_read.cpp: meghatározza a konzolalkalmazás belépési pontját. #include "stdafx.h" #include #beleértve névtér használata std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // a cirill char buff helyes megjelenítése; // az ifstream fájlból kiolvasott szöveg köztes tárolópuffere fin("cppstudio.doc"); / / ( HELYTELEN FÁJLNEVE BEADTA) if (!fin.is_open()) // ha a fájl nem open cout<< "Файл не может быть открыт!\n"; // сообщить об этом else { fin >> buff; // beolvassa az első szót a fájlból<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку } system("pause"); return 0; }

A program eredménye a 2. ábrán látható.

A fájl nem nyitható meg! Nyomjon meg egy gombot a folytatáshoz. . .

2. ábra - Fájlok kezelése C++ nyelven

Amint a 2. ábrán látható, a program azt jelentette, hogy a fájlt nem lehetett megnyitni. Ezért, ha a program fájlokkal dolgozik, akkor javasolt az is_open() függvény használata, még akkor is, ha biztos benne, hogy a fájl létezik.

Fájl megnyitási módok

A fájlmegnyitási módok határozzák meg a fájlok felhasználását. A mód beállításához az ios_base osztály konstansokat biztosít, amelyek meghatározzák a fájl megnyitási módját (lásd az 1. táblázatot).

A fájlmegnyitási módok közvetlenül beállíthatók egy objektum létrehozásakor vagy az open() függvény meghívásakor .

Offstream fout("cppstudio.txt", ios_base::app); // nyissa meg a fájlt, hogy információkat adjon a fájl végéhez fout. open("cppstudio.txt", ios_base::app); // nyissa meg a fájlt, hogy információkat adjon a fájl végéhez

A fájlmegnyitási módok bitenkénti logikai művelettel kombinálhatók vagy| , például: ios_base::out | ios_base::trunc - egy fájl megnyitása írásra a törlés után.

Az ofstream osztály objektumai, ha fájlokhoz vannak társítva, alapértelmezés szerint a fájlmegnyitási módokat tartalmazzák ios_base::out | ios_base::trunc . Vagyis a fájl létrejön, ha nem létezik. Ha a fájl létezik, akkor annak tartalma törlésre kerül, és maga a fájl készen áll a rögzítésre. Az ifstream osztály objektumai, ha egy fájlhoz vannak társítva, alapértelmezés szerint a fájlmegnyitási móddal rendelkeznek ios_base::in - a fájl csak olvasásra van nyitva. A fájlmegnyitási módot zászlónak is nevezik, az olvashatóság érdekében ezt a kifejezést fogjuk használni a jövőben. Az 1. táblázat nem sorolja fel az összes zászlót, de ezek elegendőek a kezdéshez.

Kérjük, vegye figyelembe, hogy az ate és az app jelzők leírása nagyon hasonló, mindkettő a fájl végére viszi a mutatót, de az alkalmazás jelzője csak a fájl végére teszi lehetővé az írást, az ate jelző pedig egyszerűen átrendezi a jelzőt a fájl végére. végén, és nem korlátozza a felvételi helyet.

Készítsünk programot, amely a sizeof() művelet segítségével kiszámítja a főbb C++ adattípusok jellemzőit, és fájlba írja. Jellemzők:

  1. az adattípushoz lefoglalt bájtok száma
  2. az a maximális érték, amelyet egy adott adattípus tárolhat.

A fájlba írásnak a következő formátumban kell lennie:

/* Adattípus Byte Max érték bool = 1 255,00 char = 1 255.00 Rövid int = 2 32767.00 SUNSOBLED Rövid Int = 2 65535.00 INT = 4 2147483647.00 Alkalmazott int = 4 4294967295.00 Long Int = 4 2147483647.00 hosszú úszó = 8 9223372036854775800.00 dupla = 8 9223372036854775800.00 */

Korábban már készült ilyen program a fejezetben, de ott minden adattípusra vonatkozó információ kikerült a szabványos kimeneti eszközre, és át kell alakítanunk a programot úgy, hogy az információ fájlba kerüljön. Ehhez meg kell nyitnia a fájlt írási módban, az aktuális fájl információinak előzetes csonkolásával ( 14. sor). A fájl létrehozása és sikeres megnyitása után (16-20. sorok) a cout utasítás helyett a 22. sor használja a fout objektumot. így a képernyő helyett az adattípusokra vonatkozó információk egy fájlba kerülnek.

// write_file.cpp: a konzolalkalmazás belépési pontját határozza meg. #include "stdafx.h" #include #beleértve // munka a fájlokkal #include // I/O manipulátorok névteret használó std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // csatolja az objektumot a fájlhoz, miközben a fájlt írási módban nyitja meg, minden adatot töröl belőle először fout("data_types.txt ", ios_base::out | ios_base::trunc); if (!fout.is_open()) // ha a fájl nem lett megnyitva ( cout<< "Файл не может быть открыт или создан\n"; // напечатать соответствующее сообщение return 1; // выполнить выход из программы } fout << " data type " << "byte" << " " << " max value "<< endl // oszlopfejlécek <<"bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout << "Данные успешно записаны в файл data_types.txt\n"; system("pause"); return 0; }

Nem lehet nem észrevenni, hogy a programban végrehajtott változtatások minimálisak, és mindez annak köszönhető, hogy a szabványos bemenet/kimenet és a fájl bemenet/kimenet pontosan ugyanúgy használatos. A program végén,45. sorkifejezetten lezártuk a fájlt, bár ez nem kötelező, ez jó programozási gyakorlatnak számít. Érdemes megjegyezni, hogy a szabványos bemenet/kimenet formázásához használt összes funkció és manipulátor a fájlbevitel/kimenet esetében is releváns. Ezért nem történt hiba, amikor a kezelő cout objektum váltotta fel fout.

Utolsó frissítés: 2015.10.31

Két osztályt terveztek a System.IO névtérben található könyvtárakkal való együttműködésre: Directory és DirectoryInfo .

Címtár osztály

A Directory osztály számos statikus módszert biztosít a címtárak kezelésére. Néhány ilyen módszer:

    CreateDirectory(útvonal) : létrehoz egy könyvtárat a megadott elérési úton

    Delete(path) : törli a megadott elérési útvonalon lévő könyvtárat

    Exists(path) : Meghatározza, hogy létezik-e a megadott útvonalon található könyvtár. Igaz, ha létezik, hamis értéket ad vissza, ha nem.

    GetDirectories(elérési út): Lekéri az elérési úton lévő könyvtárak listáját

    GetFiles(elérési út): Lekéri a könyvtár elérési útjában lévő fájlok listáját

    Áthelyezés(forrásDirName, destDirName): könyvtárat mozgat

    GetParent(elérési út): a szülőkönyvtár lekérése

DirectoryInfo osztály

Ez az osztály funkcionalitást biztosít a címtárak létrehozásához, törléséhez, áthelyezéséhez és egyéb címtárműveletekhez. Sok tekintetben hasonlít a Directory-hoz. Néhány tulajdonsága és módszere a következő:

    Create() : létrehoz egy könyvtárat

    CreateSubdirectory(path) : létrehoz egy alkönyvtárat a megadott elérési úton

    Delete() : töröl egy könyvtárat

    Exists tulajdonság: meghatározza, hogy a könyvtár létezik-e

    GetDirectories() : Lekéri a könyvtárak listáját

    GetFiles() : lekérheti a fájlok listáját

    MoveTo(destDirName) : áthelyez egy könyvtárat

    Szülőtulajdonság: a szülőkönyvtár lekérése

    Root tulajdonság: a gyökérkönyvtár lekérése

Nézzünk példákat ezen osztályok használatára

Fájlok és alkönyvtárak listájának lekérése

string dirName = "C:\\"; if (Directory.Exists(dirName)) ( Console.WriteLine("Alkönyvtárak:"); string dirs = Directory.GetDirectories(dirName); foreach (karakterlánc a könyvtárban) ( Console.WriteLine(s); ) Console.WriteLine( ); Console.WriteLine("Fájlok:"); string files = Directory.GetFiles(dirName); foreach (karakterláncok a fájlokban) ( Console.WriteLine(s); ) )

Vegye figyelembe a perjelek használatát a fájlnevekben. Vagy dupla perjelet használunk: "C:\\" , vagy egyszeres, de akkor a @ jelet tesszük a teljes elérési út elé: @"C:\Program Files"

Hozzon létre egy könyvtárat

karakterlánc elérési útja = @"C:\SomeDir"; string subpath = @"program\avalon"; DirectoryInfo dirInfo = new DirectoryInfo(elérési út); if (!dirInfo.Exists) ( dirInfo.Create(); ) dirInfo.CreateAlkönyvtár(alútvonal);

Először is ellenőrizzük, hogy van-e ilyen könyvtár, mert ha létezik, akkor nem lehet létrehozni, és az alkalmazás hibát dob. Ennek eredményeként a következő elérési utat kapjuk: "C:\SomeDir\program\avalon"

Információk beszerzése egy címtárról

string dirName = "C:\\Program Files"; DirectoryInfo dirInfo = new DirectoryInfo(dirName); Console.WriteLine($"Könyvtár neve: (dirInfo.Name)"); Console.WriteLine($"A könyvtár teljes neve: (dirInfo.FullName)"); Console.WriteLine($"Könyvtár létrehozási ideje: (dirInfo.CreationTime)"); Console.WriteLine($"Gyökérkönyvtár: (dirInfo.Root)");

Könyvtár törlése

Ha egyszerűen alkalmazzuk a Törlés módszert egy nem üres mappára, amely bármilyen fájlt vagy alkönyvtárat tartalmaz, akkor az alkalmazás hibát fog kiadni. Ezért egy további logikai típusú paramétert kell átadnunk a Delete metódusnak, amely jelzi, hogy a mappát teljes tartalmával együtt törölni kell:

Karakterlánc dirName = @"C:\SomeFolder"; try ( DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Könyvtár törölve"); ) catch (Exception ex) ( Console.WriteLine(ex.Message); )

Karakterlánc dirName = @"C:\SomeFolder"; Directory.Delete(dirName, true);

Könyvtár áthelyezése

string oldPath = @"C:\SomeFolder"; string newPath = @"C:\SomeDir"; DirectoryInfo dirInfo = new DirectoryInfo(oldPath); if (dirInfo.Exists && Directory.Exists(newPath) == false) ( dirInfo.MoveTo(newPath); )

Az áthelyezésnél figyelembe kell venni, hogy az új könyvtár, amelybe a régi könyvtár összes tartalmát át akarjuk helyezni, nem létezhet.

A könnyebb kezelhetőség érdekében a tárolóeszközökön lévő információkat fájl formájában tároljuk.

A fájl a külső memória egy elnevezett területe, amely adatok tömbjének tárolására van lefoglalva. A fájlokban található adatok a legkülönfélébb jellegűek: algoritmikus vagy gépi nyelvű programok; kezdeti adatok a programok működéséhez vagy a programvégrehajtás eredményei; tetszőleges szövegek; grafika stb.

Könyvtár (mappa, könyvtár) - az alkönyvtárak és fájlok nevét tartalmazó adathordozón található bájtok elnevezett gyűjteménye, amelyet a fájlrendszerben használnak a fájlok rendezésének egyszerűsítésére.

fájlrendszer az operációs rendszer funkcionális része, amely műveleteket biztosít fájlokon. Példák a fájlrendszerekre: FAT (FAT - Fájlallokációs táblázat, fájlkiosztási táblázat), NTFS, UDF (CD-ken használatos).

A FAT-nak három fő verziója létezik: FAT12, FAT16 és FAT32. A lemezszerkezetben lévő rekordok bitességében különböznek, pl. a klaszterszám tárolására lefoglalt bitek száma. A FAT12-t főleg hajlékonylemezekhez (4 KB-ig), a FAT16-ot kis lemezekhez, a FAT32-t nagy kapacitású FLASH-meghajtókhoz (32 GB-ig) használják.

Tekintsük a fájlrendszer felépítését a FAT32 használatával példaként.

FAT32 fájlszerkezet

A FAT32 rendszer külső memóriaeszközei nem bájtos, hanem blokkcímzésűek. Az információk blokkokban vagy szektorokban íródnak egy külső memóriaeszközre.

Szektor - az információ tárolásának minimális címezhető egysége a külső tárolóeszközökön. A szektor mérete általában 512 bájtban van rögzítve. A külső memóriaeszközök címterének növelése érdekében a szektorokat klasztereknek nevezett csoportokba egyesítik.

A klaszter több szektorból álló társulás, amely bizonyos tulajdonságokkal önálló egységnek tekinthető. A klaszter fő tulajdonsága a mérete, amelyet szektorok számában vagy bájtok számában mérnek.

A FAT32 fájlrendszer felépítése a következő.

A fájlok írására használt klaszterek számozása 2-től kezdődően történik. A 2-es klasztert általában a gyökérkönyvtár használja, a 3-as fürttől kezdve pedig az adattömböt tárolja. A gyökérkönyvtár feletti információk tárolására használt szektorok nincsenek fürtözve.
A lemezen a minimális fájlméret 1 fürt.

A rendszerindító szektor a következő információkkal kezdődik:

  • EB 58 90 - feltétel nélküli elágazás és aláírás;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - a bájtok száma a szektorban (általában 512);
  • 1 bájt - a fürt szektorainak száma;
  • 2 bájt - a tartalék szektorok száma.

Ezenkívül a rendszerindító szektor a következő fontos információkat tartalmazza:

  • 0x10 (1 bájt) – FAT táblák száma (általában 2);
  • 0x20 (4 bájt) - a lemezen lévő szektorok száma;
  • 0x2C (4 bájt) – gyökérkönyvtár-fürt száma;
  • 0x47 (11 bájt) – kötetcímke;
  • 0x1FE (2 bájt) - Rendszerindító szektor aláírása (55 AA).

A fájlrendszer információs szektora a következőket tartalmazza:

  • 0x00 (4 bájt) – aláírás (52 52 61 41 );
  • 0x1E4 (4 bájt) – aláírás (72 72 41 61 );
  • 0x1E8 (4 bájt) – a szabad klaszterek száma, -1, ha nem ismert;
  • 0x1EC (4 bájt) – az utolsó rögzített fürt száma;
  • 0x1FE (2 bájt) - aláírás (55 AA).

A FAT tábla információkat tartalmaz a lemezen lévő egyes fürtök állapotáról. A FAT tábla alsó 2 bájtja tárolja az F8 FF FF 0F FF FF FF FF értéket (a 0. és 1. klaszter állapotának megfelelően, fizikailag hiányzik). Továbbá az egyes fürtök állapota tartalmazza annak a fürtnek a számát, amelyben az aktuális fájl folytatódik, vagy a következő információkat:

  • 00 00 00 00 – a klaszter ingyenes;
  • FF FF FF 0F az aktuális fájl vége.
  • 8 bájt - fájlnév;
  • 3 bájt - fájlkiterjesztés;

A gyökérkönyvtár 32 bites információrekordokat tartalmaz minden egyes fájlhoz, amely a következő információkat tartalmazza:

Ha hosszú fájlnevekkel dolgozik (beleértve az orosz neveket is), a fájlnév az UTF-16 kódolási rendszerben van kódolva. Ebben az esetben minden karakter kódolásához 2 bájt van lefoglalva. Ebben az esetben a fájlnév a következő struktúrában van írva:

  • 1 bájtos sorozat;
  • 10 bájt tartalmazza a fájlnév alsó 5 karakterét;
  • 1 byte attribútum;
  • 1 bájt lefoglalva;
  • 1 bájt - DOS név ellenőrző összeg;
  • 12 bájt tartalmazza a fájlnév alsó 3 karakterét;
  • 2 bájt – az első klaszter száma;
  • a hosszú név többi karakterét.

Fájlokkal való munkavégzés C-ben

A programozó számára egy nyitott fájlt olvasott vagy írt adatok sorozataként ábrázol. Amikor egy fájlt megnyitunk, az társításra kerül I/O áramlás. A kimeneti információk a folyamba íródnak, a bemeneti információk a folyamból kerülnek kiolvasásra.

Amikor egy adatfolyamot megnyitunk I/O-hoz, az a FILE típusú szabványos struktúrához kapcsolódik, amely az stdio.h fájlban van definiálva. A FILE struktúra tartalmazza a szükséges információkat a fájlról.

A fájl megnyitása az fopen() függvénnyel történik, amely egy mutatót ad vissza egy FILE típusú struktúrára, amely felhasználható a fájl további műveleteihez.

FÁJL *fopen(név, típus);


a név a megnyitandó fájl neve (beleértve az elérési utat is),
A típus egy olyan karaktersorozatra mutató mutató, amely meghatározza a fájl elérését:
  • "r" - fájl megnyitása olvasásra (a fájlnak léteznie kell);
  • "w" - üres fájl megnyitása íráshoz; ha a fájl létezik, a tartalma elveszik;
  • "a" - fájl megnyitása a végére való íráshoz (a hozzáfűzéshez); a fájl létrejön, ha nem létezik;
  • "r+" - fájl megnyitása olvasásra és írásra (a fájlnak léteznie kell);
  • "w+" - üres fájl megnyitása olvasáshoz és íráshoz; ha a fájl létezik, a tartalma elveszik;
  • "a+" - megnyitja a fájlt olvasásra és hozzáfűzésre, ha a fájl nem létezik, akkor létrejön.

A visszatérési érték egy mutató a nyílt adatfolyamra. Ha hibát talál, NULL-t ad vissza.

Az fclose() függvény bezárja az fopen() paranccsal megnyitott fájlokhoz társított adatfolyamot vagy adatfolyamokat. A lezárandó adatfolyamot az fclose() függvény argumentuma határozza meg.

Visszatérési érték: 0 érték, ha az adatfolyamot sikeresen lezárták; az EOF állandó, ha hiba történt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#beleértve
int main() (
FÁJL *fp;
char name = "my.txt" ;
if ((fp = fopen(név, "r" )) == NULL )
{
printf( "Nem sikerült megnyitni a fájlt");
getchar();
visszatérés 0;
}
// a fájl megnyitása sikerült
... // szükséges műveletek az adatokon
fclose(fp);
getchar();
visszatérés 0;
}

Karakter beolvasása fájlból:

char fgetc(folyam);


A függvény argumentuma egy FILE típusú adatfolyamra mutató mutató. A függvény az olvasott karakter kódját adja vissza. Ha elérjük a fájl végét vagy hiba történik, az EOF konstans kerül visszaadásra.

Karakter írása fájlba:

fputc(karakter, adatfolyam);

A függvény argumentumai egy karakter és egy FILE típusú adatfolyamra mutató mutató. A függvény az olvasott karakter kódját adja vissza.

Az fscanf() és fprintf() függvények hasonlóak a scanf() és printf() függvényekhez, de adatfájlokon működnek, és egy fájlmutató az első argumentum.

fscanf(folyam, "InputFormat" , args);