Failo I/O veikimas C++ yra beveik toks pat, kaip ir įprasto I/O (tačiau su keliais niuansais).

Failų I/O klasės

Yra trys pagrindinės failų I/O klasės C++:

už srovės(yra klasės vaikas );

fstream(yra iostream klasės vaikas).

Naudodami šias klases galite atlikti vienakryptį failų įvestį, vienakryptį failų išvestį ir dvikryptį failo įvestį/išvestį. Norėdami juos naudoti, tereikia prijungti „fstream“.

Skirtingai nuo „cout“, „cin“, „cerr“ ir „clog“ srautų, kuriuos galima naudoti iš karto, failų srautus turi aiškiai nustatyti programuotojas. Tai yra, norint atidaryti failą skaitymui ir/ar rašymui, reikia sukurti atitinkamos failo I/O klasės objektą, kaip parametrą nurodant failo pavadinimą. Tada, naudodami įterpimo operatorius (<<) или извлечения (>>), galite įrašyti duomenis į failą arba skaityti failo turinį. Po to galutinis - reikia uždaryti failą: aiškiai paskambinti Uždaryti () metodas arba tiesiog leiskite failo įvesties / išvesties kintamajam išeiti iš taikymo srities (failo įvesties / išvesties klasė automatiškai uždarys tą failą už mus).

Failo išvestis

Srautinė klasė naudojama rašyti į failą. Pavyzdžiui:

#įtraukti #įtraukti #įtraukti // naudoti exit() int main() (naudojant vardų erdvę std; // ofstream naudojamas duomenims įrašyti į failą // Sukurti failą SomeText.txt ofstream outf("Kažkoks tekstas.txt"); // Jei galime 'neatidaryti šio failo norėdami įrašyti duomenis į if (!outf) ( // Tada išspausdinkite klaidos pranešimą ir paleiskite exit() cerr<< "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 автоматически закроет наш файл }

#įtraukti

#įtraukti

#įtraukti // norėdami naudoti exit()

int main ()

naudojant vardų sritį std ;

// ofstream naudojamas duomenims įrašyti į failą

// Sukurti failą SomeText.txt

ofstream outf("SomeText.txt" ) ;

// Jei negalime atidaryti šio failo ir įrašyti į jį duomenis

if(!outf)

// Tada išspausdinkite klaidos pranešimą ir paleiskite exit ()

cerr<< << endl ;

išėjimas(1) ;

// Į failą įrašykite šias dvi eilutes

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

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

grąžinti 0;

// Kai „outf“ nepatenka į taikymo sritį, srauto klasės naikintojas automatiškai uždarys mūsų failą

Jei pažvelgsite į savo projekto katalogą ( RMB skirtuke su .cpp failo pavadinimu „Visual Studio“. > „Atidaryti aplanką, kuriame yra“), pamatysite failą SomeText.txt, kuriame yra šios eilutės:

Žiūrėkite 1 eilutę!
Žiūrėkite 2 eilutę!

Atkreipkite dėmesį, kad mes taip pat galime naudoti put() metodas norėdami įrašyti vieną simbolį į failą.

Failo įvestis

#įtraukti #įtraukti #įtraukti #įtraukti // norėdami naudoti exit() int main() ( naudojant vardų erdvę std; // ifstream naudojamas failo turiniui nuskaityti // Pabandykite perskaityti failo SomeText.txt turinį ifstream inf("KažkasText.txt") ; // Jei negalime atidaryti šio failo ir perskaityti jo turinį 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; }

#įtraukti

#įtraukti

#įtraukti

#įtraukti // norėdami naudoti exit()

int main ()

naudojant vardų sritį std ;

// ifstream naudojamas failo turiniui nuskaityti

// Jei negalime atidaryti šio failo ir perskaityti jo turinį

jei(!inf)

// Tada išspausdinkite šį klaidos pranešimą ir paleiskite exit ()

cerr<< << endl ;

išėjimas(1) ;

// Kol yra duomenų, galime skaityti

o (inf)

// Tada šiuos duomenis perkeliame į eilutę, kurią tada rodome ekrane

string strInput ;

inf >> strInput ;

cout<< strInput << endl ;

grąžinti 0;

// Kai inf nepatenka į taikymo sritį, ifstream klasės naikintojas automatiškai uždarys mūsų failą

Pamatyti
linija
#1!
Pamatyti
linija
#2!

Hmm, ne visai to norėjome. Kaip jau žinome iš ankstesnių pamokų, ištraukimo operatorius dirba su „suformatuotais duomenimis“, t.y. jis nepaiso visų tarpų, skirtukų ir naujų eilučių. Norėdami perskaityti visą turinį tokį, koks yra, neskaidydami jo į dalis (kaip aukščiau pateiktame pavyzdyje), turime naudoti getline() metodas:

#įtraukti #įtraukti #įtraukti #įtraukti // naudoti exit() int main() ( naudojant vardų erdvę std; // ifstream naudojamas failų turiniui nuskaityti // Bandysime nuskaityti failo SomeText.txt turinį ifstream inf("SomeText.txt") ; // Jei negalime atidaryti failo ir perskaityti jo turinį if (!inf) ( // Tada išspausdinkite šį klaidos pranešimą ir išeikite () cerr<< "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 автоматически закроет наш файл }

#įtraukti

#įtraukti

#įtraukti

#įtraukti // norėdami naudoti exit()

int main ()

naudojant vardų sritį std ;

// ifstream naudojamas failų turiniui skaityti

ifstream inf("SomeText.txt" ) ;

// Jei negalime atidaryti failo ir perskaityti jo turinį

jei(!inf)

// Tada išspausdinkite šį klaidos pranešimą ir paleiskite exit ()

cerr<< "Oi, SomeText.txt nepavyko atidaryti skaitymui!"<< endl ;

išėjimas(1) ;

o (inf)

string strInput ;

getline (inf , strInput );

cout<< strInput << endl ;

grąžinti 0;

// Kai inf nepatenka į taikymo sritį, ifstream klasės naikintojas automatiškai uždarys mūsų failą

Aukščiau pateiktos programos vykdymo rezultatas yra:

buferinė išvestis

Išvestis C++ gali būti buferizuota. Tai reiškia, kad viskas, kas išvedama į failų srautą, negali būti iš karto įrašyta į diską (į konkretų failą). Tai pirmiausia daroma dėl našumo priežasčių. Kai buferio duomenys įrašomi į diską, tai vadinama buferio išvalymas. Vienas iš būdų išvalyti buferį yra uždaryti failą. Tokiu atveju visas buferio turinys bus perkeltas į diską, o tada failas bus uždarytas.

Išvesties buferis paprastai nėra problema, tačiau tam tikromis aplinkybėmis tai gali sukelti problemų neatsargiems naujokams. Pavyzdžiui, kai duomenys saugomi buferyje ir programa nutraukia vykdymą anksčiau laiko (dėl gedimo arba iškvietus ). Tokiais atvejais failų I/O klasės naikintuvai nevykdomi, failai niekada neuždaromi, buferiai neišplaunami, o mūsų duomenys prarandami amžiams. Štai kodėl prieš iškviečiant exit() patartina aiškiai uždaryti visus atidarytus failus.

Taip pat galite išvalyti buferį rankiniu būdu, naudodami ostream::flush() metodas arba siunčiant std::flushį išvesties srautą. Bet kuris iš šių metodų gali būti naudingas siekiant užtikrinti, kad programos gedimo atveju buferio turinys būtų nedelsiant įrašytas į diską.

Įdomus niuansas: Nes std::endl; taip pat išvalo išvesties srautą, tada per didelis jo naudojimas (dėl to bus nereikalingas buferio plovimas) gali turėti įtakos programos veikimui (nes kai kuriais atvejais buferio plovimas gali būti brangus). Dėl šios priežasties našumą vertinantys programuotojai dažnai naudoja \n vietoj std::endl, norėdami įterpti naują eilutę į išvesties srautą, kad būtų išvengta nereikalingo buferio plovimo.

Failų atidarymo režimai

Kas atsitiks, jei bandysime įrašyti duomenis į jau esamą failą? Pakartotinai paleidus aukščiau esančią programą (pati pirmą), rodoma, kad pradinis failas visiškai perrašomas, kai paleidžiate programą dar kartą. Bet ką daryti, jei mums reikia pridėti duomenų prie failo pabaigos? Pasirodo, failo srautas pasirenka antrąjį parametrą, leidžiantį nurodyti programuotojui, kaip atidaryti failą. Kaip šį parametrą galite praeiti sekančios vėliavos(kurie yra „ios“ klasėje):

programėlė- atidaro failą pridėjimo režimu;

valgė- eina į failo pabaigą prieš skaitydamas/rašydamas;

dvejetainis- atidaro failą dvejetainiu režimu (vietoj teksto režimo);

in- atidaro failą skaitymo režimu (numatytasis ifstream);

išeiti- atidaro failą rašymo režimu (numatytasis ofstream);

trumpinti- ištrina failą, jei jis jau yra.

Galite nurodyti kelias vėliavėles vienu metu naudodami .

pagal numatytuosius nustatymus ifstream veikia ios::in režimu;

ofstream veikia ios::out režimu pagal numatytuosius nustatymus;

Pagal numatytuosius nustatymus fstream veikia ios::in OR ios::out režimu, o tai reiškia, kad galite skaityti failo turinį arba įrašyti duomenis į failą.

Dabar parašykime programą, kuri prie anksčiau sukurto SomeText.txt failo pridės dvi eilutes:

#įtraukti #įtraukti // norėdami naudoti exit() #include int main() ( naudojant vardų erdvę std; // Perduodami vėliavėlę ios:app, kad praneštume fstream, kad pridėsime savo duomenis prie jau esamų failo duomenų, // failo neperrašysime. nereikia perduoti ios::out vėliavėlės , // nes ofstream numatytasis nustatymas yra ios::out ofstream outf("SomeText.txt", ios::app); // Jei negalime atidaryti failo duomenims įrašyti, jei (!outf) ( // Tada išveskite šį klaidos pranešimą ir išeikite () 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 автоматически закроет наш файл }

#įtraukti

#įtraukti // norėdami naudoti exit()

#įtraukti

int main ()

naudojant vardų sritį std ;

// Perduodami vėliavėlę ios:app, kad praneštumėte fstream, kad pridėsime savo duomenis prie jau esamų failo duomenų,

// mes neketiname perrašyti failo. Mums nereikia perduoti ios::out vėliavėlės,

// nes ofstream numatytasis ios::out režimas

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

// Jei negalime atidaryti failo duomenims įrašyti

if(!outf)

// Tada išspausdinkite šį klaidos pranešimą ir paleiskite exit ()

cerr<< "Oi, SomeText.txt nepavyko atidaryti rašymui!"<< endl ;

išėjimas(1) ;

Įvesties / išvesties mechanizmas, kurį sukūrė , neatitinka šiandien visuotinai priimto objektinio programavimo stiliaus, be to, aktyviai naudoja rodyklės operacijas, kurios šiuolaikinėse saugaus kodo vykdymo aplinkose laikomos potencialiai nesaugiomis. Alternatyva programų kūrimui yra standartinis I/O klasės mechanizmas, kurį suteikia C++ kalbos standartas.

Failų atidarymas

Dažniausiai naudojamos klasės yra ifstream skaitymui, ofstream – rašymui ir fstream – failų keitimui.

Visos srieginės įvesties / išvesties klasės yra netiesiogiai išvestos iš bendro protėvio ios, visiškai paveldėdamos jos funkcionalumą. Pavyzdžiui, išvardintų duomenų narys open_mode nurodo failo atidarymo režimą, kuris apibrėžiamas taip:

Enum open_mode ( programa, dvejetainis, in, out, trunc, ate );

Žemiau pateikiamos galimos vėliavų vertės ir jų paskirtis.

Pavyzdžiui, norėdami atidaryti failą test.txt ir skaityti dvejetainius duomenis, turėtumėte parašyti:

ifstream failas; file.open("test.txt", ios::in | ios::binary);

Loginis ARBA operatorius (|) leidžia sudaryti režimą su bet kokiu vėliavėlių deriniu. Kad atidarydami failą rašydami netyčia neperrašytumėte esamo failo tuo pačiu pavadinimu, turite naudoti šią formą:

ne srautinis failas; file.open("test.txt", ios::out | ios::app);

Daroma prielaida, kad atitinkamas antraštės failas yra prijungtas prie projekto:

#įtraukti

Norėdami patikrinti, ar failas buvo sėkmingai atidarytas, galite naudoti konstrukciją

If (!file) ( // Failo atidarymo klaida )

Įtraukimo ir išgavimo operatoriai

Nepaisoma failų tvarkymo klasėse įtraukti operatorių (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

failą<< "Это строка текста";

Taip pat galite rašyti teksto eilutę dalimis:

failą<< "Это " << "строка " << "текста";

Endl sakinys baigia eilutės įvestį karietos grįžimu:

failą<< "Это строка текста" << endl;

Naudojant įtraukimo operatorių, į failą lengva įrašyti kintamųjų ar masyvo elementų reikšmes:

Srautinio failo („Temp.txt“); char buff = "Teksto masyve yra kintamųjų"; int vx = 100; float pi = 3,14159; failą<< buff << endl << vx << endl << pi << endl;

Vykdant kodą sukuriamos trys teksto failo Temp.txt eilutės:

Teksto masyve yra kintamieji 100 3.14159

Atminkite, kad skaitinės reikšmės į failą įrašomos kaip tekstinės eilutės, o ne dvejetainės reikšmės.

ekstrakto operatorius(>>) veikia priešingai. Atrodytų, kad norint ištraukti simbolius iš anksčiau parašyto Temp.txt failo, reikia parašyti tokį kodą:

ifstream failas ("Temp.txt"); char buff; intvx; floatpi; failas >> buff >> vx >> pi;

Tačiau ištraukimo operatorius sustos ties pirmuoju skiriamuoju ženklu (tarpo, tabuliavimo ar naujos eilutės), su kuriuo susiduria. Taigi, analizuojant sakinį "Teksto masyve yra kintamųjų", į masyvo buff bus įrašytas tik žodis "Tekstas", tarpas ignoruojamas, o žodis "masyvas" taps sveikojo skaičiaus kintamojo vx ir kodo reikšme. Vykdymas „pasibaigs“ neišvengiamu duomenų struktūros pažeidimu. Toliau, aptardami ifstream klasę, parodysime, kaip teisingai organizuoti failo skaitymą iš ankstesnio pavyzdžio.

ifstream klasė: failų skaitymas

Kaip rodo pavadinimas, ifstream klasė skirta įvesti failo srautą. Pagrindiniai klasės metodai yra išvardyti žemiau. Dauguma jų yra paveldėti iš istream klasės ir perkrauti pirminėmis funkcijomis. Pavyzdžiui, funkcija get, priklausomai nuo iškvietimo parametro, gali nuskaityti ne tik vieną simbolį, bet ir simbolių bloką.

Dabar aišku, kaip reikia modifikuoti ankstesnį pavyzdį, kad duomenų ištraukimo operatorius gautų laukiamą rezultatą:

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

Getline metodas nuskaitys pirmąją failo eilutę iki galo, o operatorius >> priskirs reikšmes kintamiesiems.

Šiame pavyzdyje parodytas duomenų įtraukimas į tekstinį failą ir viso failo skaitymas. Ciklas while (1) naudojamas vietoj while(!file2.eof()) dėl priežasčių, aptartų .

#įtraukti #įtraukti naudojant vardų sritį std; int main() ( ofstream failas; file.open("test.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; }

Šis pavyzdys perskaito eilutes iš failo test.txt ir rodo jas konsolėje.

#įtraukti #įtraukti naudojant vardų sritį std; int main() ( ifstream failas; // sukurti srauto objekto failą file.open("test.txt"); // atidaryti failą skaitymui if (!file) return 1; // grįžti, kai klaida atidaroma char str; / / statinis eilučių buferis // Skaityti ir rodyti eilutes cikle, kol eof while (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Šis kodas Windows OS taip pat priklauso nuo naujos eilutės simbolio buvimo paskutinėje failo eilutėje, būtų patikimiau tai padaryti:

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

Aiškūs atidarymo ir uždarymo metodų iškvietimai yra neprivalomi. Iš tiesų, konstruktoriaus iškvietimas su argumentu leidžia nedelsiant atidaryti failą tuo metu, kai sukuriamas failo srauto objektas:

ifstream failas("test.txt");

Vietoj uždarymo metodo galite naudoti trynimo operatorių, kuris automatiškai iškvies failo objekto naikintuvą ir uždarys failą. Nors ciklo kodas užtikrina tinkamą failo pabaigos patikrinimą.

ofstream klasė: failų rašymas

Srautinio srauto klasė skirta išvesti duomenis iš failų srauto. Žemiau pateikiami pagrindiniai šios klasės metodai.

Anksčiau aprašytas įtraukimo operatorius yra patogus organizuojant rašymą į tekstinį failą:

Srautinio failo („temp.txt“); if (!file) return; už (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Dvejetainiai

Iš esmės dvejetainiai duomenys pateikiami kaip tekstiniai duomenys. Skirtumas tas, kad jei dvejetainiai duomenys rašomi tam tikra logine struktūra, tai jie turi būti nuskaitomi iš failo į to paties struktūros tipo kintamąjį.

Pirmasis rašymo ir skaitymo metodų parametras (rašymo/skaitymo bloko adresas) turi būti simbolio rodyklės tipo char * , todėl reikia aiškiai konvertuoti negalios * struktūros adreso tipą. Antrasis parametras nurodo, kad failo dvejetainiai blokai turi pastovų baitų dydį, neatsižvelgiant į faktinį įrašo ilgį. Šiame priede pateikiamas pavyzdys, kaip sukurti ir rodyti duomenis paprastoje užrašų knygelėje. Tada failo įrašai skaitomi paeiliui ir rodomi konsolėje.

#įtraukti #įtraukti #įtraukti naudojant vardų sritį std; struct Pastabos ( // bloknoto duomenų struktūra char Vardas; // visas vardas char Telefonas; // telefonas int Amžius; // amžius ); int main() ( setlocale(LC_ALL, "rusų kalba"); Pastabos Note1= ("Grozny Ioann Vasilyevich", "neįdiegta", 60 ); Pastabos Note2= ("Godunovas Borisas Fedorovičius", "095-111-2233", 30 ); Notes3= ( "Petras Romanovas ", "812-333-2211", 20 ); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof ( Pastabos)); // 1-asis blokas ofile.write((char*)&Note2, sizeof(Notes)); // 2-asis blokas ofile.write((char*)&Note3, sizeof(Notes)); / / 3-asis blokas ofile. close (); // uždarykite parašytą failą ifstream ifile ("Notebook.dat", ios::binary); Pastabos Pastaba; // struktūrinis kintamasis char str; // statinis eilutės buferis // Skaitykite ir rodykite eilutes cikle, kol eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tBody: %s\tAge: %d" , Note.Name, Note. Telefonas, pastaba.Amžius); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

Vykdant šį kodą iš trijų blokų po 80 baitų susidaro dvejetainis failas Notebook.dat (darant prielaidą, kad simboliai yra vieno baito). Žinoma, galite naudoti kitus srautinio perdavimo būdus ir atlikti bet kokias operacijas tam tikros duomenų struktūros laukuose.

fstream klasė: atsitiktinė prieiga prie failų

Tarkime, kad mūsų sąsiuvinyje yra 100 įrašų, o mes norime suskaičiuoti 50. Žinoma, galite organizuoti kilpą ir perskaityti visus įrašus nuo pirmojo iki pateikto. Akivaizdu, kad tikslingesnis sprendimas yra nustatyti pos failo padėties žymeklį tiesiai į 50 įrašą ir jį perskaityti:

ifstream ifile("Notebook.dat", ios::binary); int poz = 49 * sizeof(Pastabos); ifile seek(pos); // ieškoti 50-ojo įrašo Pastabos Pastaba; //Pastabos – aukščiau aprašyta "įrašo" struktūra ifile.read((char*)&Note, sizeof(Notes));

Tokios paieškos operacijos yra veiksmingos, jei failą sudaro žinomo ir pastovaus dydžio įrašai. Norėdami pakeisti savavališko įrašo turinį, turite atidaryti išvesties srautą modifikavimo režimu:

Offstream ofile ("Notebook.dat", ios::binary | ios::ate); int poz = 49 * sizeof(Pastabos); ofile seekp(pos); // ieškoti 50-osios natos Notes Note50 = ("Jelcinas Borisas Nikolajevičius", "095-222-3322", 64); ofile.write((char*)&Pastaba, dydis(Pastabos)); // pakeitimas

Jei nenurodysite ios::ate (arba ios::app) vėliavėlės, atidarius dvejetainį failą Notebook.dat, ankstesnis jo turinys bus ištrintas!

Galiausiai galima vienu metu atidaryti failą skaitymui / rašymui, naudojant metodus, kuriuos fstream srautinio perdavimo klasė paveldėjo iš savo pirmtakų. Kadangi fstream klasė yra kilusi iš istream ir ostream (atitinkamai ifstream ir ofstream tėvai), visi anksčiau paminėti metodai tampa prieinami programai.

Toliau pateiktame pavyzdyje sukeičiamas pirmasis ir trečiasis failo Notebook.dat įrašai.

#įtraukti #įtraukti #įtraukti naudojant vardų sritį std; struct Pastabos ( char Vardas; char Telefonas; int Amžius; ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Atidaryti failą, skirtą skaityti / rašyti vienu metu fstream file ("Notebook.dat", ios::binary | ios::in | ios:: out); file.seekg(2 * sizeof(Notes)); // rasti ir skaityti Note3 failą.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // rasti ir skaityti Note1 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; }

ios::in ir ios::out vėliavėlės turi būti nurodytos failo objekto konstruktoriuje, kad būtų galima vienu metu atlikti skaitymo ir rašymo operacijas. Vykdant šį kodą bus sukeisti pirmasis ir trečiasis dvejetainio Notebook.dat failo įrašai.

Yra papildomų pavyzdžių šia tema.

Dauguma kompiuterių programų dirba su failais, todėl reikia kurti, trinti, rašyti, skaityti, atidaryti failus. Kas yra failas? Failas yra pavadintas baitų rinkinys, kuris gali būti saugomas tam tikrame saugojimo įrenginyje. Na, dabar aišku, kad failas yra tam tikra baitų seka, turinti savo unikalų pavadinimą, pvz., .txt failas. Failai tuo pačiu pavadinimu negali būti tame pačiame kataloge. Failo pavadinimas suprantamas ne tik kaip jo pavadinimas, bet ir kaip plėtinys, pavyzdžiui: failas.txt ir failas.dat skirtingi failai, nors jie turi tą patį pavadinimą. Yra toks dalykas kaip pilnas failų pavadinimas – tai visas adresas į failų katalogą su failo pavadinimu, pavyzdžiui: D:\docs\file.txt . Svarbu suprasti šias pagrindines sąvokas, kitaip bus sunku dirbti su failais.

Norėdami dirbti su failais, turite įtraukti antraštės failą . AT apibrėžtos kelios klasės ir įtraukti antraštės failai failo įvestis ir failo išvestis.

Failo I/O panašus į standartinį I/O, skirtumas tik tas, kad I/O daroma ne ekrane, o faile. Jei įvestis/išvestis į standartinius įrenginius atliekami naudojant cin ir cout objektus, tai norint sutvarkyti failą I/O, pakanka sukurti savo objektus, kurie gali būti naudojami panašiai kaip cin ir cout operatoriai.

Pavyzdžiui, reikia sukurti tekstinį failą ir į jį įrašyti eilutę Darbas su failais C++. Norėdami tai padaryti, turite atlikti šiuos veiksmus:

  1. sukurti srauto klasės objektą ;
  2. susieti klasės objektą su failu, į kurį bus rašoma;
  3. įrašyti eilutę į failą;
  4. uždaryti failą.

Kodėl reikia sukurti ofstream klasės, o ne ifstream klasės objektą? Kadangi reikia rašyti į failą, o jei reikia nuskaityti duomenis iš failo, tada būtų sukurtas ifstream klasės objektas.

// sukurti objektą, kurį norite įrašyti į srauto failą /*objekto pavadinimas*/; // srauto klasės objektas

Pavadinkime objektą - fout , Štai kas atsitinka:

Išorinis fout;

Kodėl mums reikia objekto? Objektas reikalingas, kad galėtų rašyti į failą. Objektas jau sukurtas, bet nesusietas su failu, į kurį turi būti įrašyta eilutė.

fout.open("cppstudio.txt"); // susieti objektą su failu

Per taškinę operaciją gauname prieigą prie open() klasės metodo, kurio skliausteliuose nurodome failo pavadinimą. Nurodytas failas bus sukurtas esamame kataloge su programa. Jei yra failas tokiu pat pavadinimu, esamas failas bus pakeistas nauju. Taigi, failas atidarytas, belieka į jį įrašyti norimą eilutę. Tai daroma taip:

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

Naudojant perdavimo srautui operaciją kartu su objektu fout, eilutė File Handling programoje C++ įrašoma į failą. Kadangi nebereikia keisti failo turinio, jis turi būti uždarytas, tai yra, objektas turi būti atskirtas nuo failo.

fout.close(); // uždarykite failą

Dėl to buvo sukurtas failas su eilute Darbas su failais C++.

1 ir 2 žingsnius galima sujungti, tai yra vienoje eilutėje sukurti objektą ir susieti jį su failu. Tai daroma taip:

Ofstream fout("cppstudio.txt"); // sukurti ofstream klasės objektą ir susieti jį su cppstudio.txt failu

Sujungkime visą kodą ir gaukime tokią programą.

// failas.cpp: apibrėžia konsolės programos įėjimo tašką. #include "stdafx.h" #include naudojant vardų sritį std; int main(int argc, char* argv) ( ofstream fout("cppstudio.txt"); // sukurti ofstream klasės objektą rašymui ir susieti jį su failu cppstudio.txt fout<< "Работа с файлами в С++"; // запись строки в файл fout.close(); // закрываем файл system("pause"); return 0; }

Belieka patikrinti, ar tinkamai veikia programa, ir tam atidarome failą cppstudio.txt ir pažiūrėkite į jo turinį, tai turėtų būti Darbas su failais C++.

  1. sukurti ifstream klasės objektą ir susieti jį su failu, iš kurio bus skaitoma;
  2. skaityti failą;
  3. uždaryti failą.
// file_read.cpp: apibrėžia konsolės programos įėjimo tašką. #include "stdafx.h" #include #įtraukti naudojant vardų sritį std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // teisingas kirilicos abėcėlės rodymas char buff; // tarpinis teksto, nuskaityto iš failo ifstream, saugojimo buferis fin ("cppstudio.txt" "); // atidarytas failas, skirtas skaityti fin >><< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку system("pause"); return 0; }

Programa rodo du būdus, kaip skaityti iš failo: pirmasis naudoja perkėlimo į srautą operaciją, antrasis naudoja funkciją getline () . Pirmuoju atveju skaitomas tik pirmasis žodis, o antruoju – 50 simbolių eilutė. Tačiau kadangi faile liko mažiau nei 50 simbolių, simboliai skaitomi iki paskutinio imtinai. Atkreipkite dėmesį, kad skaitykite antrą kartą (17 eilutė) tęsėsi po pirmojo žodžio, o ne nuo pradžios, nes buvo perskaitytas pirmasis žodis14 eilutė. Programos rezultatas parodytas 1 pav.

Darbas su failais C++ Paspauskite bet kurį klavišą, kad tęstumėte. . .

1 pav. Darbas su failais C++

Programa veikė teisingai, tačiau taip būna ne visada, net jei su kodu viskas tvarkoje. Pavyzdžiui, programai buvo perduotas neegzistuojančio failo pavadinimas arba pavadinime buvo padaryta klaida. Kas tada? Tokiu atveju nieko nebus. Failas nerastas, vadinasi, jo perskaityti neįmanoma. Todėl kompiliatorius nepaisys eilučių, kuriose yra manipuliuojama failu. Dėl to programa bus tinkamai uždaryta, tačiau ekrane nieko nebus rodoma. Atrodytų, tai visiškai normali reakcija į tokią situaciją. Tačiau paprastas vartotojas nesupras, kas yra ir kodėl ekrane nepasirodė eilutė iš failo. Taigi, kad viskas būtų labai aišku, C++ suteikia tokią funkciją - is_open() , kuri grąžina sveikąsias reikšmes: 1 - jei failas buvo sėkmingai atidarytas, 0 - jei failas nebuvo atidarytas. Baigkime programą failo atidarymu taip, kad jei failas neatidaromas, būtų rodomas atitinkamas pranešimas.

// file_read.cpp: apibrėžia konsolės programos įėjimo tašką. #include "stdafx.h" #include #įtraukti naudojant vardų sritį std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // teisingas kirilicos char buff atvaizdavimas; // tarpinis saugojimo buferis teksto, nuskaityto iš failo ifstream fin("cppstudio.doc"); / / ( ĮVEDĖTAS NETEISINGAS FAILOS PAVADINIMAS) if (!fin.is_open()) // jei failas nėra atviras cout<< "Файл не может быть открыт!\n"; // сообщить об этом else { fin >> buff; // skaitykite pirmąjį žodį iš failo cout<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку } system("pause"); return 0; }

Programos rezultatas parodytas 2 pav.

Failo atidaryti negalima! Paspauskite bet kurį klavišą norėdami tęsti. . .

2 pav. Darbas su failais C++

Kaip matote iš 2 paveikslo, programa pranešė, kad failo atidaryti nepavyko. Todėl, jei programa dirba su failais, rekomenduojama naudoti šią funkciją is_open() , net jei esate tikri, kad failas egzistuoja.

Failų atidarymo režimai

Failų atidarymo režimai nustato, kaip naudojami failai. Norėdami nustatyti režimą, ios_base klasė pateikia konstantas, kurios nustato failo atidarymo režimą (žr. 1 lentelę).

Failų atidarymo režimus galima nustatyti tiesiogiai kuriant objektą arba iškviečiant funkciją open(). .

Ofstream fout("cppstudio.txt", ios_base::app); // atidaryti failą, kad į failo pabaigą pridėtumėte informacijos fout. open("cppstudio.txt", ios_base::app); // atidarykite failą, kad pridėtumėte informacijos prie failo pabaigos

Failo atidarymo režimai gali būti derinami naudojant bitų loginę operaciją arba| , pavyzdžiui: ios_base::out | ios_base::trunc – atidarykite failą rašymui, jį išvalę.

Klasės ofstream objektuose, susietuose su failais, pagal numatytuosius nustatymus yra failo atidarymo režimai ios_base::out | ios_base::trunc . Tai reiškia, kad failas bus sukurtas, jei jo nėra. Jei failas yra, jo turinys bus ištrintas, o pats failas bus paruoštas įrašyti. Ifstream klasės objektai, susieti su failu, pagal numatytuosius nustatymus turi failo atidarymo režimą ios_base::in – failas yra atviras tik skaitymui. Failų atidarymo režimas dar vadinamas vėliavėle, todėl skaitymui šį terminą naudosime ateityje. 1 lentelėje nėra išvardytos visos vėliavėlės, tačiau jų turėtų pakakti, kad galėtumėte pradėti.

Atkreipkite dėmesį, kad „ate“ ir „app“ vėliavėlės aprašymu yra labai panašios, jos abi perkelia žymeklį į failo pabaigą, tačiau programos vėliavėlė leidžia rašyti tik į failo pabaigą, o „ate“ vėliavėlė tiesiog pertvarko vėliavėlę į failo pabaigą. pabaigos ir neriboja įrašymo vietos.

Sukurkime programą, kuri naudodama operaciją sizeof() apskaičiuos pagrindinių duomenų tipų charakteristikas C++ kalboje ir įrašys jas į failą. Charakteristikos:

  1. baitų, skirtų duomenų tipui, skaičius
  2. didžiausia vertė, kurią gali saugoti konkretus duomenų tipas.

Rašymas į failą turi būti tokio formato:

/* Duomenų tipas baitas Max Value BOOL = 1 255.00 Char = 1 255.00 Trumpas int = 2 32767.00 nepasirašytas trumpas int = 2 65535.00 int = 4 2147483647.00 nepasirašytas int = 4 4294967295.00 Long Int = 4 2147483647.00 nepasirašytas int = 4 4294967295.00 Long Int = 4 2147483647.00 nepasirašytas int = 4 4294967295.00 Long Int = 4 2147483647.00 nepasirašytas int = 4 4294967295.00 Long Int = 4 2147483647.00 nepasirašytas int = 4 4294967295.00 Long Int = 4 2147483647.00 ilga plūdė = 8 9223372036854775800.00 dviguba = 8 9223372036854775800.00 */

Tokia programa jau buvo sukurta ankščiau skyriuje, tačiau ten visa informacija apie duomenų tipus buvo išvesta į standartinį išvesties įrenginį ir reikia perdaryti programą taip, kad informacija būtų įrašyta į failą. Norėdami tai padaryti, turite atidaryti failą rašymo režimu, iš anksto sutrumpinę esamo failo informaciją ( 14 eilutė). Sukūrus ir sėkmingai atidarius failą (16–20 eilutės), vietoj cout teiginio, 22 eilutė naudokite fout objektą. taigi, vietoj ekrano, informacija apie duomenų tipus bus įrašyta į failą.

// write_file.cpp: apibrėžia konsolės programos įėjimo tašką. #include "stdafx.h" #include #įtraukti // dirbti su failais #include // I/O manipuliatoriai, naudojantys vardų erdvę std; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // susiekite objektą su failu, atidarydami failą rašymo režimu, ištrindami visus duomenis iš jo pirmiausia iš srauto fout ("data_types.txt" ", ios_base::out | ios_base::trunc); if (!fout.is_open()) // jei failas nebuvo atidarytas ( cout<< "Файл не может быть открыт или создан\n"; // напечатать соответствующее сообщение return 1; // выполнить выход из программы } fout << " data type " << "byte" << " " << " max value "<< endl // stulpelių antraštės <<"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; }

Neįmanoma nepastebėti, kad programos pakeitimai yra minimalūs, ir visa tai dėka to, kad standartinis įvestis/išvestis ir failo įvestis/išvestis naudojami lygiai taip pat. Pasibaigus programai,45 eilutėmes aiškiai uždarėme failą, nors tai nėra būtina, tai laikoma gera programavimo praktika. Verta pažymėti, kad visos funkcijos ir manipuliatoriai, naudojami standartiniam įvesties/išvesties formatavimui, yra aktualūs ir failų įvesties/išvesties atveju. Todėl, kai operatorius neįvyko klaidų cout buvo pakeistas objektu fout.

Paskutinis atnaujinimas: 2015-10-31

Dvi klasės skirtos dirbti su katalogais System.IO vardų erdvėje: Directory ir DirectoryInfo .

Katalogų klasė

Katalogų klasė suteikia daugybę statinių katalogų valdymo metodų. Kai kurie iš šių metodų yra:

    CreateDirectory(kelias) : sukuria katalogą nurodytu keliu

    Ištrinti(kelias) : ištrina nurodyto kelio katalogą

    Egzistuoja(kelias) : nustato, ar nurodytame kelyje esantis katalogas egzistuoja. Grąžina tiesa, jei yra, false, jei ne.

    GetDirectories(kelias) : Gauna katalogų, esančių kelyje, sąrašą

    GetFiles(kelias) : Gauna failų sąrašą katalogo kelyje

    Perkelti(sourceDirName, destDirName): perkelia katalogą

    GetParent(kelias): gaukite pirminį katalogą

DirectoryInfo klasė

Ši klasė suteikia galimybę kurti, ištrinti, perkelti ir atlikti kitas katalogo operacijas. Daugeliu atžvilgių jis panašus į katalogą. Kai kurios jo savybės ir metodai yra šie:

    Create() : sukuria katalogą

    CreateSubdirectory(path) : sukuria pakatalogį nurodytu keliu

    Delete() : ištrina katalogą

    Ypatybė Exists: nustato, ar katalogas egzistuoja

    GetDirectories() : Gauna katalogų sąrašą

    GetFiles() : gaukite failų sąrašą

    MoveTo(destDirName) : perkelia katalogą

    Pirminė nuosavybė: gauti pirminį katalogą

    Šakninė nuosavybė: gauti šakninį katalogą

Pažvelkime į šių klasių naudojimo pavyzdžius

Failų ir pakatalogių sąrašo gavimas

eilutė dirName = "C:\\"; if (Directory.Exists(dirName)) ( Console.WriteLine("Pakatalogiai:"); string dirs = Directory.GetDirectories(dirName); foreach (eilutė s kataloguose) ( Console.WriteLine(s); ) Console.WriteLine( ); Console.WriteLine("Failai:"); string files = Directory.GetFiles(dirName); foreach (eilutė failuose) ( Console.WriteLine(s); ) )

Atkreipkite dėmesį į pasvirųjų brūkšnių naudojimą failų pavadinimuose. Arba naudojame dvigubą pasvirąjį brūkšnį: "C:\\" , arba vieną, bet tada prieš visą kelią dedame ženklą @: @"C:\Program Files"

Sukurkite katalogą

eilutės kelias = @"C:\SomeDir"; string subpath = @"program\avalon"; DirectoryInfo dirInfo = naujas DirectoryInfo(kelias); if (!dirInfo.Exists) ( dirInfo.Create(); ) dirInfo.CreateSubdirectory(subpath);

Pirmiausia patikriname, ar toks katalogas yra, nes jei jis yra, tada jo sukurti nepavyks, o programa išmes klaidą. Dėl to mes gausime šį kelią: "C:\SomeDir\program\avalon"

Informacijos apie katalogą gavimas

string dirName = "C:\\Programų failai"; DirectoryInfo dirInfo = naujas KatalogoInformacija(kataloName); Console.WriteLine($"Katalogo pavadinimas: (dirInfo.Name)"); Console.WriteLine($"Visas katalogo pavadinimas: (dirInfo.FullName)"); Console.WriteLine($"Katalogo sukūrimo laikas: (dirInfo.CreationTime)"); Console.WriteLine($"Šakninis katalogas: (dirInfo.Root)");

Katalogo ištrynimas

Jei paprasčiausiai taikysime trynimo metodą netuščiam aplankui, kuriame yra failų ar pakatalogių, programa išmes klaidą. Todėl Delete metodui turime perduoti papildomą loginio tipo parametrą, kuris nurodys, kad aplankas turi būti ištrintas su visu jo turiniu:

Eilutė dirName = @"C:\SomeFolder"; try ( DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Katalogas ištrintas"); ) gaudyti (Exclusive ex) ( Console.WriteLine(ex.Message); )

Eilutė dirName = @"C:\SomeFolder"; Katalogas.Ištrinti(dirName, true);

Katalogo perkėlimas

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

Perkeldami turime atsižvelgti į tai, kad naujojo katalogo, į kurį norime perkelti visą senojo katalogo turinį, neturi būti.

Kad būtų lengviau tvarkyti, informacija saugojimo įrenginiuose saugoma failų pavidalu.

Failas yra pavadinta išorinės atminties sritis, skirta duomenų masyvo saugojimui. Failuose esantys duomenys yra pačių įvairiausių: programos algoritmine arba mašinine kalba; pradiniai programų veikimo duomenys arba programos vykdymo rezultatai; savavališki tekstai; grafika ir kt.

Katalogas (aplankas, katalogas) - pavadintas baitų rinkinys laikmenoje, kuriame yra pakatalogių ir failų pavadinimai, naudojamas failų sistemoje, siekiant supaprastinti failų organizavimą.

Failų sistema yra funkcinė operacinės sistemos dalis, teikianti operacijas su failais. Failų sistemų pavyzdžiai yra FAT (FAT – failų paskirstymo lentelė, failų paskirstymo lentelė), NTFS, UDF (naudojami kompaktiniuose diskuose).

Yra trys pagrindinės FAT versijos: FAT12, FAT16 ir FAT32. Jie skiriasi disko struktūros įrašų bitumu, t.y. bitų skaičius, skirtas saugoti klasterio numerį. FAT12 daugiausia naudojamas diskeliams (iki 4 KB), FAT16 – mažiems diskams, FAT32 – didelės talpos FLASH diskams (iki 32 GB).

Apsvarstykite failų sistemos struktūrą naudodami FAT32 kaip pavyzdį.

FAT32 failo struktūra

Išorinės atminties įrenginiai FAT32 sistemoje yra ne baitinis, o blokinis adresavimas. Informacija įrašoma į išorinį atminties įrenginį blokais arba sektoriais.

Sektorius – minimalus adresuojamas informacijos saugojimo išoriniuose atminties įrenginiuose vienetas. Paprastai sektoriaus dydis yra fiksuotas 512 baitų. Siekiant padidinti išorinių atminties įrenginių adresų erdvę, sektoriai sujungiami į grupes, vadinamas klasteriais.

Klasteris yra kelių sektorių asociacija, kurią galima laikyti savarankišku vienetu, turinčiu tam tikrų savybių. Pagrindinė klasterio savybė yra jo dydis, matuojamas sektorių skaičiumi arba baitų skaičiumi.

FAT32 failų sistema turi tokią struktūrą.

Failų rašymui naudojami klasteriai numeruojami pradedant nuo 2. Klasterį #2 paprastai naudoja šakninis katalogas, o pradedant nuo 3 klasterio, saugomas duomenų masyvas. Sektoriai, naudojami informacijai saugoti virš šakninio katalogo, nėra sugrupuoti.
Mažiausias failo dydis diske yra 1 klasteris.

Įkrovos sektorius prasideda tokia informacija:

  • EB 58 90 - besąlyginis filialas ir parašas;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - baitų skaičius sektoriuje (dažniausiai 512);
  • 1 baitas – sektorių skaičius klasteryje;
  • 2 baitai – atsarginių sektorių skaičius.

Be to, įkrovos sektoriuje yra ši svarbi informacija:

  • 0x10 (1 baitas) – FAT lentelių skaičius (dažniausiai 2);
  • 0x20 (4 baitai) - sektorių skaičius diske;
  • 0x2C (4 baitai) – šakninio katalogo klasterio numeris;
  • 0x47 (11 baitų) – tūrio etiketė;
  • 0x1FE (2 baitai) – įkrovos sektoriaus parašas (55 AA).

Failų sistemos informacijos sektoriuje yra:

  • 0x00 (4 baitai) – parašas (52 52 61 41 );
  • 0x1E4 (4 baitai) – parašas (72 72 41 61 );
  • 0x1E8 (4 baitai) – laisvų klasterių skaičius, -1, jei nežinoma;
  • 0x1EC (4 baitai) – paskutinio įrašyto klasterio numeris;
  • 0x1FE (2 baitai) - parašas (55 AA).

FAT lentelėje yra informacija apie kiekvienos grupės diske būseną. Apatiniai 2 FAT lentelės saugyklos baitai F8 FF FF 0F FF FF FF FF (atitinka 0 ir 1 klasterių būseną, fiziškai nėra). Be to, kiekvienos klasterio būsenoje yra klasterio, kuriame tęsiasi dabartinis failas, numeris arba ši informacija:

  • 00 00 00 00 – klasteris nemokamas;
  • FF FF FF 0F yra dabartinio failo pabaiga.
  • 8 baitai - failo pavadinimas;
  • 3 baitai - failo plėtinys;

Šakniniame kataloge yra kiekvieno failo 32 bitų informacijos įrašų rinkinys, kuriame yra ši informacija:

Dirbant su ilgais failų pavadinimais (įskaitant rusiškus), failo pavadinimas yra užkoduotas UTF-16 kodavimo sistemoje. Šiuo atveju kiekvienam simboliui koduoti skiriami 2 baitai. Šiuo atveju failo pavadinimas rašomas tokios struktūros forma:

  • 1 baito seka;
  • 10 baitų yra 5 apatiniai failo pavadinimo simboliai;
  • 1 baito atributas;
  • 1 baitas rezervuotas;
  • 1 baitas - DOS vardo kontrolinė suma;
  • 12 baitų yra 3 apatiniai failo pavadinimo simboliai;
  • 2 baitai – pirmo klasterio numeris;
  • likusieji ilgojo vardo simboliai.

Darbas su failais C

Programuotojui atidarytas failas yra vaizduojamas kaip skaitomų arba įrašomų duomenų seka. Kai failas atidaromas, jis susiejamas su I/O srautas. Išvesties informacija įrašoma į srautą, įvesties informacija nuskaitoma iš srauto.

Kai srautas atidaromas I/O, jis susiejamas su standartine FILE tipo struktūra, kuri apibrėžta stdio.h . FILE struktūroje yra reikalinga informacija apie failą.

Failas atidaromas naudojant funkciją fopen(), kuri grąžina žymeklį į FILE tipo struktūrą, kurią galima naudoti tolimesnėms failo operacijoms.

FAILAS *fopen(vardas, tipas);


pavadinimas yra failo, kurį reikia atidaryti, pavadinimas (įskaitant kelią),
tipas yra žymeklis į simbolių eilutę, kuri apibrėžia, kaip failas pasiekiamas:
  • "r" - atidaryti failą skaitymui (failas turi egzistuoti);
  • "w" - atidarykite tuščią failą rašymui; jei failas egzistuoja, jo turinys prarandamas;
  • "a" - atidaryti failą rašyti iki galo (pridėti); failas sukuriamas, jei jo nėra;
  • "r+" - atidarykite failą skaitymui ir rašymui (failas turi egzistuoti);
  • "w+" - atidarykite tuščią failą skaitymui ir rašymui; jei failas egzistuoja, jo turinys prarandamas;
  • "a+" - atidarykite failą skaitymui ir pridėjimui, jei failo nėra, jis sukuriamas.

Grąžinama vertė yra rodyklė į atvirą srautą. Jei randama klaida, grąžinama NULL.

Funkcija fclose() uždaro srautą arba srautus, susietus su failais, atidarytais naudojant fopen(). Uždaromas srautas nustatomas pagal funkcijos fclose() argumentą.

Grąžinama reikšmė: vertė 0, jei srautas buvo sėkmingai uždarytas; EOF konstanta, jei įvyko klaida.

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

#įtraukti
int main() (
FILE *fp;
char pavadinimas = "mano.txt" ;
if ((fp = fopen(vardas, "r" )) == NULL )
{
printf( "Nepavyko atidaryti failo");
getchar ();
grąžinti 0;
}
// pavyko atidaryti failą
... // būtini veiksmai su duomenimis
fclose(fp);
getchar ();
grąžinti 0;
}

Simbolio skaitymas iš failo:

char fgetc(srautas);


Funkcijos argumentas yra rodyklė į FILE tipo srautą. Funkcija grąžina perskaityto simbolio kodą. Jei pasiekiama failo pabaiga arba įvyksta klaida, grąžinama EOF konstanta.

Simbolio įrašymas į failą:

fputc(simbolis, srautas);

Funkcijos argumentai yra simbolis ir rodyklė į FILE tipo srautą. Funkcija grąžina perskaityto simbolio kodą.

Funkcijos fscanf() ir fprintf() yra panašios į scanf() ir printf() funkcijas, tačiau veikia duomenų failuose ir jų pirmasis argumentas yra failo žymeklis.

fscanf(stream, "InputFormat" , args);