Rad s datotekama u C-u, unos i izlaz u datoteku u C-u. Rad s tekstualnim datotekama Rad s tekstualnim datotekama


Datotečni I/O u C++ radi gotovo identično uobičajenom I/O (ali s nekoliko manjih razlika).

I/O klase datoteka

Jesti tri glavne I/O klase datoteka u C++:

ofstream(je dijete razreda);

fstream(dijete je klase iostream).

Koristeći ove klase, možete izvoditi jednosmjerni ulaz datoteke, jednosmjerni izlaz datoteke i dvosmjerni I/O datoteke. Da biste ih koristili, samo trebate spojiti fstream.

Za razliku od tokova cout, cin, cerr i clog, koji se mogu odmah koristiti, tokove datoteka mora izričito instalirati programer. To jest, da biste otvorili datoteku za čitanje i/ili pisanje, morate kreirati objekt odgovarajuće I/O klase datoteke, navodeći naziv datoteke kao parametar. Zatim, koristeći operatore umetanja (<<) или извлечения (>>), možete pisati podatke u datoteku ili čitati sadržaj datoteke. Nakon ovoga, posljednja stvar je zatvaranje datoteke: eksplicitni poziv metoda close(). ili samo pustite da I/O varijabla datoteke izađe izvan opsega (I/O klasa datoteke će automatski zatvoriti tu datoteku umjesto nas).

Izlaz datoteke

Za pisanje u datoteku koristi se klasa ofstream. Na primjer:

#uključi #uključi #uključi // koristiti exit() int main() ( koristeći namespace std; // ofstream se koristi za pisanje podataka u datoteku // Stvaranje datoteke SomeText.txt ofstream outf("SomeText.txt"); // Ako možemo Ne otvaraj ovu datoteku za pisanje podataka u if (!outf) ( // Zatim prikaži poruku o pogrešci i izvrši 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 автоматически закроет наш файл }

#uključi

#uključi

#uključi // koristiti exit()

int main()

korištenje imenskog prostora std;

// ofstream se koristi za pisanje podataka u datoteku

// Kreirajte datoteku SomeText.txt

ofstream outf("SomeText.txt");

// Ako ne možemo otvoriti ovu datoteku da u nju upišemo podatke

ako(!outf)

// Zatim prikazujemo poruku o pogrešci i izvršavamo exit()

cerr<< << endl ;

izlaz(1);

// Napišite sljedeća dva retka u datoteku

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

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

vratiti 0;

// Kada outf izađe iz opsega, destruktor ofstream klase automatski će zatvoriti našu datoteku

Ako pogledate u svoj direktorij projekta ( Kliknite desnom tipkom miša na karticu s nazivom vaše .cpp datoteke u Visual Studiju > "Otvori mapu koja sadrži"), vidjet ćete datoteku pod nazivom SomeText.txt koja sadrži sljedeće retke:

Pogledajte liniju #1!
Pogledajte liniju #2!

Imajte na umu da također možemo koristiti metodu put(). za pisanje jednog znaka u datoteku.

Unos datoteke

#uključi #uključi #uključi #uključi // koristiti exit() int main() ( koristeći namespace std; // ifstream se koristi za čitanje sadržaja datoteke // Pokušajmo pročitati sadržaj datoteke SomeText.txt ifstream inf("SomeText.txt" ); // Ako ne možemo otvoriti ovu datoteku da bismo pročitali njezin sadržaj 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; }

#uključi

#uključi

#uključi

#uključi // koristiti exit()

int main()

korištenje imenskog prostora std;

// ifstream se koristi za čitanje sadržaja datoteke

// Ako ne možemo otvoriti ovu datoteku da pročitamo njezin sadržaj

ako (! inf)

// Zatim ispisujemo sljedeću poruku o pogrešci i izvršavamo exit()

cerr<< << endl ;

izlaz(1);

// Sve dok postoje podaci koje možemo čitati

dok (inf)

// Zatim te podatke premještamo u redak koji potom prikazujemo na ekranu

niz strInput;

inf >> strInput ;

cout<< strInput << endl ;

vratiti 0;

// Kada inf izađe iz opsega, ifstream destruktor klase automatski će zatvoriti našu datoteku

Vidjeti
crta
#1!
Vidjeti
crta
#2!

Hmm, to nije baš ono što smo htjeli. Kao što već znamo iz prethodnih lekcija, operator ekstrakta radi s "formatiranim podacima", tj. zanemaruje sve razmake, kartice i nove retke. Da bismo pročitali sav sadržaj kakav jest, a da ga ne dijelimo na dijelove (kao u gornjem primjeru), moramo koristiti metoda getline().:

#uključi #uključi #uključi #uključi // koristiti exit() int main() ( koristeći namespace std; // ifstream se koristi za čitanje sadržaja datoteka // Pokušat ćemo pročitati sadržaj datoteke SomeText.txt ifstream inf("SomeText.txt" ); // Ako ne možemo otvoriti datoteku da bismo pročitali njezin sadržaj if (!inf) ( // Zatim ispišite sljedeću poruku o pogrešci i izvršite exit() 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 автоматически закроет наш файл }

#uključi

#uključi

#uključi

#uključi // koristiti exit()

int main()

korištenje imenskog prostora std;

// ifstream se koristi za čitanje sadržaja datoteka

ifstream inf ("SomeText.txt" ) ;

// Ako ne možemo otvoriti datoteku da pročitamo njezin sadržaj

ako (! inf)

// Zatim ispisujemo sljedeću poruku o pogrešci i izvršavamo exit()

cerr<< "Oh, SomeText.txt nije bilo moguće otvoriti za čitanje!"<< endl ;

izlaz(1);

dok (inf)

niz strInput;

getline(inf, strInput);

cout<< strInput << endl ;

vratiti 0;

// Kada inf izađe iz opsega, ifstream destruktor klase automatski će zatvoriti našu datoteku

Rezultat pokretanja gornjeg programa:

Izlaz u međuspremniku

Izlaz u C++ može se spremiti u međuspremnik. To znači da se sve što je izlazno u tok datoteke ne može odmah zapisati na disk (u određenu datoteku). To se prvenstveno radi zbog performansi. Kada se podaci međuspremnika zapišu na disk, on se poziva čišćenje međuspremnika. Jedan od načina brisanja međuspremnika je zatvaranje datoteke. U tom će slučaju cijeli sadržaj međuspremnika biti premješten na disk, a zatim će se datoteka zatvoriti.

Spremanje izlaza u međuspremnik obično nije problem, ali pod određenim okolnostima može uzrokovati probleme neopreznim početnicima. Na primjer, kada se podaci pohranjuju u međuspremnik i program se prerano prekine (bilo kao rezultat greške ili pozivanjem ). U takvim slučajevima, destruktori I/O klasa datoteka se ne izvršavaju, datoteke se nikada ne zatvaraju, međuspremnici se ne ispiraju, a naši podaci se zauvijek gube. Zbog toga je dobra ideja izričito zatvoriti sve otvorene datoteke prije pozivanja exit().

Možete također ručno očistiti međuspremnik pomoću ostream::flush() metoda ili slanjem std::ispiranje na izlazni tok. Bilo koja od ovih metoda može biti korisna u osiguravanju da se sadržaj međuspremnika odmah zapisuje na disk u slučaju kvara programa.

Zanimljiva nijansa: Jer std::endl; također čisti izlazni tok, njegova prekomjerna upotreba (koja rezultira nepotrebnim ispiranjem međuspremnika) može utjecati na performanse programa (budući da ispiranje međuspremnika u nekim slučajevima može biti skupa operacija). Iz tog razloga, programeri koji brinu o performansama svog koda često koriste \n umjesto std::endl za umetanje znaka novog retka u izlazni tok, kako bi izbjegli nepotrebno ispiranje međuspremnika.

Načini otvaranja datoteka

Što se događa ako pokušamo zapisati podatke u već postojeću datoteku? Ponovno pokretanje gornjeg programa (prvog) pokazuje da je izvorna datoteka potpuno prebrisana kada ponovno pokrenete program. Što ako trebamo dodati podatke na kraj datoteke? Ispostavilo se da tok datoteke uzima izborni drugi parametar, koji vam omogućuje da kažete programeru kako da otvori datoteku. Ovaj parametar možete proslijediti kao sljedeće zastave(koji su u ios klasi):

aplikacija- otvara datoteku u načinu dodavanja;

jeli- ide na kraj datoteke prije čitanja/pisanja;

binarni- otvara datoteku u binarnom načinu (umjesto tekstualnog);

u- otvara datoteku u načinu čitanja (zadano za ifstream);

van- otvara datoteku u načinu snimanja (zadano za ofstream);

trunc- briše datoteku ako već postoji.

Možete navesti više zastavica odjednom pomoću .

ifstream prema zadanim postavkama radi u načinu rada ios::in;

ofstream prema zadanim postavkama radi u ios::out modu;

fstream prema zadanim postavkama radi u ios::in OR ios::out modu, što znači da možete čitati sadržaj datoteke ili pisati podatke u datoteku.

Sada napišimo program koji će dodati dva retka u prethodno kreiranu datoteku SomeText.txt:

#uključi #uključi // za korištenje exit() #include int main() ( koristeći namespace std; // Proslijedite oznaku ios:app da kažete fstreamu da ćemo svoje podatke dodati postojećim podacima datoteke, // nećemo prebrisati datoteku. Mi ne ne treba proslijediti zastavu ios::out, // budući da ofstream prema zadanim postavkama radi u ios::out modu ofstream outf("SomeText.txt", ios::app); // Ako ne možemo otvoriti datoteku za pisanje podataka if (!outf) ( // Zatim šaljemo sljedeću poruku o pogrešci i izvršavamo 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 автоматически закроет наш файл }

#uključi

#uključi // koristiti exit()

#uključi

int main()

korištenje imenskog prostora std;

// Proslijedite oznaku ios:app da kažete fstreamu da ćemo svoje podatke dodati postojećim podacima datoteke,

// nećemo prebrisati datoteku. Ne trebamo proslijediti oznaku ios::out,

// jer ofstream prema zadanim postavkama radi u ios::out modu

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

// Ako ne možemo otvoriti datoteku za pisanje podataka

ako(!outf)

// Zatim ispisujemo sljedeću poruku o pogrešci i izvršavamo exit()

cerr<< "Oh, SomeText.txt nije bilo moguće otvoriti za pisanje!"<< endl ;

izlaz(1);

I/O mehanizam koji je razvio , nije u skladu s općeprihvaćenim stilom objektno orijentiranog programiranja danas, osim toga, uvelike koristi pokazivačke operacije koje se smatraju potencijalno nesigurnima u modernim okruženjima za sigurno izvršavanje koda. Alternativa pri razvoju aplikacijskih aplikacija je mehanizam standardnih I/O klasa koje pruža standard jezika C++.

Otvaranje datoteka

Najčešće korištene klase su ifstream za čitanje, ofstream za pisanje i fstream za modificiranje datoteka.

Sve navojne I/O klase neizravno su izvedene iz zajedničkog pretka ios-a, u potpunosti nasljeđujući njegovu funkcionalnost. Dakle, način otvaranja datoteke određen je podatkovnim članom tipa enumeracije open_mode, koji je definiran na sljedeći način:

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

Ispod su moguće vrijednosti zastavica i njihova namjena.

Na primjer, da biste otvorili datoteku pod nazivom test.txt za čitanje podataka u binarnom obliku, napisali biste:

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

Logički OR operator (|) omogućuje vam stvaranje načina s bilo kojom kombinacijom zastavica. Dakle, kako prilikom otvaranja datoteke unosom ne biste slučajno prebrisali postojeću datoteku s istim imenom, morate koristiti sljedeći obrazac:

Ofstream datoteka; file.open("test.txt", ios::out | ios::app);

Pretpostavlja se da je odgovarajuća datoteka zaglavlja uključena u projekt:

#uključi

Kako biste provjerili je li datoteka uspješno otvorena, možete koristiti konstrukciju

If (!file) ( //Rukovanje pogreškom otvaranja datoteke)

Operatori uključivanja i izdvajanja

Nadjačano u klasama rukovanja datotekama operator uključivanja (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

Datoteka<< "Это строка текста";

Također možete pisati tekstualni niz u dijelovima:

Datoteka<< "Это " << "строка " << "текста";

Naredba endl završava unos retka povratkom na početak reda:

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

Pomoću operatora uključivanja, lako je napisati vrijednosti varijabli ili elemenata niza u datoteku:

Ofstream datoteka ("Temp.txt"); char buff = "Tekstualni niz sadrži varijable"; int vx = 100; float pi = 3,14159; datoteka<< buff << endl << vx << endl << pi << endl;

Kao rezultat izvršavanja koda formiraju se tri reda tekstualne datoteke Temp.txt:

Tekstualni niz sadrži varijable 100 3.14159

Imajte na umu da se numeričke vrijednosti zapisuju u datoteku kao tekstualni nizovi, a ne kao binarne vrijednosti.

Operator za dohvaćanje(>>) proizvodi suprotan učinak. Čini se da biste za izdvajanje znakova iz ranije napisane datoteke Temp.txt trebali napisati kôd poput sljedećeg:

Ifstream datoteka ("Temp.txt"); char buff; int vx; plovak pi; datoteka >> buff >> vx >> pi;

Međutim, operator ekstrakcije zaustavit će se na prvom graničniku na koji naiđe (razmak, tabulator ili novi red). Dakle, prilikom raščlanjivanja rečenice "Tekstni niz sadrži varijable", samo će riječ "Tekst" biti zapisana u buff niz, razmak se zanemaruje, a riječ "niz" postat će vrijednost cijele vx varijable, a kod izvršenje će "poći po zlu" s neizbježnim kršenjem strukture podataka. Zatim ćemo, kada budemo raspravljali o klasi ifstream, pokazati kako pravilno organizirati čitanje datoteke iz prethodnog primjera.

klasa ifstream: čitanje datoteka

Kao što naziv sugerira, klasa ifstream dizajnirana je za unos toka datoteke. Glavne metode klase navedene su u nastavku. Većina ih je naslijeđena od istream klase i preopterećena kako bi proširila nadređenu funkcionalnost. Na primjer, funkcija get, ovisno o parametru poziva, može čitati ne samo jedan znak, već i blok znakova.

Sada je jasno kako prethodni primjer treba modificirati tako da korištenje operatora ekstrakcije podataka daje očekivani rezultat:

Ifstream datoteka ("Temp.txt"); char buff; int vx; plovak pi; file.getline(buff, sizeof(buff)); datoteka >> vx >> pi:

Getline metoda će pročitati prvi redak datoteke do kraja, a >> operator će dodijeliti vrijednosti varijablama.

Sljedeći primjer prikazuje dodavanje podataka u tekstualnu datoteku i zatim čitanje cijele datoteke. Petlja while(1) koristi se umjesto while(!file2.eof()) iz razloga koji su razmatrani u .

#uključi #uključi korištenje imenskog prostora std; int main() ( ofstream datoteka; 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; }

Sljedeći primjer prikazuje petlju koja čita retke iz datoteke test.txt i prikazuje ih na konzoli.

#uključi #uključi korištenje imenskog prostora std; int main() ( ifstream datoteka; // kreira datoteku objekta toka file.open("test.txt"); // otvori datoteku za čitanje if (!file) return 1; // povratak na grešku otvaranja char str; // statički međuspremnik reda // Čitanje i prikaz redaka u petlji do eof while (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Ovaj kod pod Windows OS-om također ovisi o prisutnosti znaka novog retka u zadnjem retku datoteke; bilo bi pouzdanije učiniti ovo:

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

Eksplicitni pozivi metoda otvaranja i zatvaranja nisu potrebni. Doista, pozivanje konstruktora s argumentom omogućuje vam da odmah otvorite datoteku, u trenutku stvaranja objekta datoteke s nitima:

Ifstream datoteka("test.txt");

Umjesto metode zatvaranja, možete koristiti operator brisanja, koji će automatski pozvati destruktor datotečnog objekta i zatvoriti datoteku. Kod petlje while osigurava ispravne provjere kraja datoteke.

ofstream klasa: pisanje datoteka

Klasa ofstream dizajnirana je za izlaz podataka iz toka datoteke. Slijedi popis glavnih metoda ove klase.

Ranije opisan operator uključivanja prikladan je za organiziranje pisanja u tekstualnu datoteku:

Ofstream datoteka ("temp.txt"); if (!file) povratak; za (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Binarne datoteke

U principu, binarni podaci se tretiraju kao tekstualni podaci. Razlika je u tome što ako su binarni podaci zapisani u specifičnoj logičkoj strukturi, onda se moraju pročitati iz datoteke u varijablu istog tipa strukture.

Prvi parametar metoda pisanja i čitanja (adresa bloka pisanja/čitanja) mora biti karakternog pokazivača tipa char * , stoga je potrebno izvršiti eksplicitnu konverziju tipa adrese void * strukture. Drugi parametar specificira da binarni blokovi datoteke imaju konstantnu veličinu bajta bez obzira na stvarnu duljinu zapisa. Sljedeća aplikacija pruža primjer stvaranja i prikaza podataka u jednostavnoj bilježnici. Unosi datoteka se zatim čitaju uzastopno i prikazuju na konzoli.

#uključi #uključi #uključi korištenje imenskog prostora std; struct Bilješke ( // struktura podataka bilježnice char Ime; // puno ime char Telefon; // phone int Dob; // dob); int main() ( setlocale(LC_ALL, "Ruski"); Notes Note1= ("The Terrible Ioann Vasilyevich", "nije instalirano", 60 ); Notes Note2= ("Godunov Boris Fedorovich", "095-111-2233" , 30 ); Bilješke Note3= ( "Romanov Petr Mikhailovich ", "812-333-2211 ", 20 ); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof (Notes)); // 1. blok ofile.write((char*)&Note2, sizeof(Notes)); // 2. blok ofile.write((char*)&Note3, sizeof(Notes)); / / 3. blok ofile.close(); // zatvori snimljenu datoteku ifstream ifile("Notebook.dat", ios::binary); Bilješke Napomena; // strukturirana varijabla char str; // statički međuspremnik niza // Čitanje i prikaz redaka u petlja do eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tTelefon: %s\tDob: %d" , Note.Name, Napomena.Telefon, Napomena.Dob); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

Kao rezultat izvršavanja ovog koda, formira se binarna datoteka Notebook.dat od tri bloka od po 80 bajtova (pod pretpostavkom da su znakovi jednobajtni). Naravno, možete koristiti druge metode niti i izvoditi bilo koje operacije na poljima određene strukture podataka.

fstream klasa: slučajni pristup datoteci

Pretpostavimo da imamo 100 unosa u našoj bilježnici, a želimo prebrojati 50. Naravno, možete organizirati petlju i čitati sve zapise od prvog do zadanog. Očito je ciljanije rješenje postaviti pokazivač položaja pos datoteke izravno na unos 50 i čitati iz njega:

Ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Napomene); ifile.seekg(pos); // traženje 50. Bilješke Note; //Bilješke – struktura "zapisa" opisana iznad ifile.read((char*)&Note, sizeof(Notes));

Takve operacije pretraživanja učinkovite su ako se datoteka sastoji od zapisa poznate i stalne veličine. Da biste zamijenili sadržaj proizvoljnog zapisa, morate otvoriti izlazni tok u načinu modifikacije:

Ofstream ofile ("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Napomene); ofile seekp(pos); // traži 50. bilješku Notes Note50 = ("Yeltsin Boris Nikolaevich", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Notes)); // zamjena

Ako ne navedete oznaku ios::ate (ili ios::app), kada otvorite binarnu datoteku Notebook.dat, njezin će prethodni sadržaj biti izbrisan!

Konačno, moguće je istovremeno otvoriti datoteku za čitanje/pisanje, korištenjem metoda naslijeđenih od fstream klase strujanja od svojih prethodnika. Budući da je klasa fstream izvedena iz istream i ostream (roditelji ifstreama i ofstreama), sve ranije spomenute metode postaju dostupne u aplikaciji.

Sljedeći primjer prikazuje preuređivanje prvog i trećeg unosa u datoteci Notebook.dat.

#uključi #uključi #uključi korištenje imenskog prostora std; struct Bilješke (char Ime; char Telefon; int Dob; ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Otvaranje datoteke za istovremeno čitanje/pisanje fstream file("Notebook.dat", ios::binary | ios::in | ios: : out); file.seekg(2 * sizeof(Notes)); // pronađi i pročitaj Note3 file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // pronađi i pročitaj 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; }

U konstruktoru datotečnog objekta morate navesti zastavice ios::in i ios::out, dopuštajući istodobne operacije čitanja i pisanja. Kao rezultat izvršavanja ovog koda, prvi i treći unos u binarnoj datoteci Notebook.dat bit će zamijenjeni.

Postoje dodatni primjeri na temu.

U ovom ćemo članku naučiti kako čitati podatke iz datoteka i pisati informacije u datoteke u C programima. Datoteke u C koriste se za spremanje rezultata C programa i korištenje pri ponovnom pokretanju programa. Na primjer, možete spremiti rezultate izračuna i statistiku igre.
Za rad s datotekama u C-u morate uključiti biblioteku stdio.h
#uključi
Za rad datoteka u C potrebno je odrediti pokazivač na datoteku prema primjeru
DATOTEKA *ime pokazivača datoteke;
Na primjer
TURPIJA *peraja;
Određuje fin pokazivač na datoteku
Zatim morate otvoriti datoteku i povezati je s pokazivačem datoteke. Da biste otvorili datoteku u C-u za čitanje, koristite naredbu
File pointer name= fopen("put do datoteke", "r");
Na primjer sljedeća naredba
fin = fopen("C:\\Korisnici\\korisnik\\Desktop\\data.txt", "r");
otvorit će datoteku data.txt, koja se nalazi na radnoj površini duž staze C:\\Users\\user\\Desktop Da biste saznali stazu do datoteke, možete odabrati datoteku mišem, kliknuti desnom tipkom miša i odaberite svojstva datoteke. Odjeljak Lokacija pokazat će put do datoteke. Imajte na umu da je u C put označen pomoću dvije kose crte.
Nakon rada s datotekom u C-u, morate je zatvoriti pomoću naredbe
fclose(ime pokazivača datoteke)

Čitanje informacija iz tekstualne datoteke u C

Da biste mogli čitati ruske znakove iz datoteke, morate konfigurirati rad s ćirilicom pomoću naredbe
setlocale(LC_ALL, "ruski");

U tom slučaju trebate uključiti #include na početku programa

fscanf() operator

Za čitanje riječi iz datoteka u C koristi se naredba fscanf(). Ova naredba je slična naredbi za unos podataka s tipkovnice, samo što je prvi parametar pokazivač na datoteku
fscanf(pokazivač datoteke,"%format unosa podataka1% format unosa podataka2...",&varijabla1,&varijabla2...);
Na primjer naredba
fscanf(fin,"%d%d%d",&a,&b,&c);
čita niz od tri cjelobrojne varijable iz datoteke koja je povezana s pokazivačem datoteke fin
Pogledajmo primjer programa koji čita informacije iz tekstualne datoteke data.txt u kojoj su zapisana tri stupca brojeva i zapisuje ih u nizove. Svaki stupac informacija ima svoj niz. Pojedinosti o.
#uključi
#uključi
glavni()
(int a;
int b;
int c;
int i;
// definirati pokazivač na datoteku
TURPIJA *peraja;
// otvori datoteku za čitanje
fin = fopen("C:\\Korisnici\\korisnik\\Desktop\\data.txt", "r");
// red po red čitanje iz datoteke
za (i=0;i<3;i++)
{
// čitanje niza iz tri vrijednosti datoteke i zapisivanje u nizove
fscanf(fin,"%d%d%d",&a[i],&b[i],&c[i]);
}
// prikaz nizova na ekranu
za (i=0;i<3;i++)
{
printf("%d %d %d ",a[i],b[i],c[i]);
}
dobiti();
// zatvaranje datoteke
fclose(peraja);
}

Line-by-line čitanje informacija iz datoteke u SI. Funkcija fgets ()

Operator fscanf() čita riječ iz datoteke, tj. na prvi prostor na koji naiđe.
Za čitanje cijelog retka iz datoteke u C-u upotrijebite konstrukciju
if (NULL != fgets (varijabla niza, duljina niza, pokazivač datoteke))
{
radnje pri čitanju retka
}

Na primjer, C program koji čita dva retka iz datoteke i prikazuje ih na ekranu
#uključi
#uključi
#uključi
glavni()
{
// postavljanje varijabli niza
char st1;
char st2;
//definirajte pokazivač na datoteku
TURPIJA *peraja;
// postaviti rad s ćirilicom
setlocale(LC_ALL, "ruski");
// otvori datoteku za čitanje
fin = fopen("C:\\data.txt", "r");
// čitanje prvog reda iz datoteke
if (NULL != fgets (st1, 100, fin))
{
// prikaz niza na ekranu
printf("%s ",st1);)
// čitanje drugog reda iz datoteke
if (NULL != fgets (st2, 100, fin))
{
// prikaz niza na ekranu
printf("%s ",st2);)
// zatvori datoteku za čitanje
fclose(peraja);
}

Zapisivanje informacija u tekstualnu datoteku u C-u

Za snimanje podataka u datoteku u C, trebate otvoriti datoteku u načinu snimanja
File pointer name= fopen("put do datoteke", "w");
Za pisanje u redak u tekstualnoj datoteci koristite naredbu fprnitf(), koja je slična naredbi u C-u, samo što je prvi parametar pokazivač na datoteku
fprintf (naziv pokazivača datoteke, "% ulazni format", varijable);
Na primjer, pisanje vrijednosti varijable a u datoteku out.txt
a=10;
fout = fopen("C:\\Korisnici\\korisnik\\Desktop\\out.txt", "w");
fprintf(fout,"%d", a);

Primjer C programa koji zahtijeva dva broja i zapisuje oba broja i njihov zbroj u datoteku out.txt

#uključi
#uključi

glavni()
(int a;
int b;
int c;
DATOTEKA *fout;
fout = fopen("C:\\Korisnici\\korisnik\\Desktop\\out.txt", "w");
printf("unesi prvi broj");
scanf("%d", &a);
printf("unesi drugi broj");
scanf("%d", &b);
c=a+b;
fprintf(fout,"%d %d %d",a,b,c);
dobiti();
fclose(četiri);
}

Prethodno smo prilikom unosa i izlaza podataka radili sa standardnim tokovima - tipkovnicom i monitorom. Sada pogledajmo kako jezik C implementira primanje podataka iz datoteka i njihovo zapisivanje tamo. Prije nego što možete izvršiti ove operacije, morate otvoriti datoteku i pristupiti joj.

U programskom jeziku C, pokazivač na datoteku je tipa FILE i njegova deklaracija izgleda ovako:
DATOTEKA *moja datoteka;

S druge strane, funkcija fopen() otvara datoteku na adresi navedenoj kao prvi argument u načinu čitanja ("r"), načinu pisanja ("w") ili načinu dodavanja ("a") i vraća pokazivač na to na program. Stoga proces otvaranja datoteke i povezivanja s programom izgleda otprilike ovako:
moja datoteka = fopen("zdravo.txt", "r");

Prilikom čitanja ili pisanja podataka u datoteku, pristupa se preko pokazivača datoteke (u ovom slučaju, myfile).

Ako iz jednog ili drugog razloga (nema datoteke na navedenoj adresi, pristup joj je odbijen) funkcija fopen() ne može otvoriti datoteku, tada vraća NULL. U pravim programima, oni gotovo uvijek rješavaju pogrešku pri otvaranju datoteke u grani if, ali to ćemo dalje izostaviti.

Deklaracija funkcije fopen() sadržana je u datoteci zaglavlja stdio.h, pa mora biti uključena. Također u stdio.h tip strukture FILE je deklariran.

Nakon što je rad s datotekom završen, uobičajeno je zatvoriti je kako bi se međuspremnik oslobodio podataka i iz drugih razloga. Ovo je osobito važno ako program nastavi raditi nakon rada s datotekom. Prekidanje veze između vanjske datoteke i pokazivača na nju iz programa vrši se pomoću funkcije fclose(). Pokazivač na datoteku prosljeđuje joj se kao parametar:
fclose(mojadatoteka);

U programu se može otvoriti više od jedne datoteke. U tom slučaju svaka datoteka mora biti povezana s vlastitim pokazivačem datoteke. Međutim, ako program prvo radi s jednom datotekom, a zatim je zatvori, tada se pokazivač može koristiti za otvaranje druge datoteke.

Čitanje iz tekstualne datoteke i pisanje u nju

fscanf()

Funkcija fscanf() po značenju je slična funkciji scanf(), ali za razliku od nje pruža formatirani unos iz datoteke umjesto standardnog unosa. Funkcija fscanf() uzima parametre: pokazivač datoteke, niz formata, adrese memorijskih područja za upisivanje podataka:
fscanf(mojadatoteka, "%s%d", str, &a);

Vraća broj uspješno pročitanih podataka ili EOF. Razmaci i znakovi novog retka računaju se kao razdjelnici podataka.

Recimo da imamo datoteku koja sadrži sljedeći opis objekata:

Jabuke 10 23,4 banane 5 25,0 kruh 1 10,3

#uključi main () ( FILE * file; struct food ( char name[ 20 ] ; unsigned qty; float price; ) ; struct food shop[ 10 ] ; char i= 0 ; file = fopen ( "fscanf.txt" , "r" ) ; while (fscanf (datoteka, "%s%u%f" , trgovina[ i].naziv, & (trgovina[ i].količina) , & (trgovina[ i].cijena ) ) != EOF) ( printf ("%s %u %.2f \n", trgovina[ i].naziv, trgovina[ i].količina, trgovina[ i].cijena) ; i++; ) )

U ovom slučaju deklariraju se struktura i niz struktura. Svaki redak iz datoteke odgovara jednom elementu niza; element polja je struktura koja sadrži niz i dva numerička polja. Petlja čita jedan red po iteraciji. Kada se naiđe na kraj datoteke, fscanf() vraća EOF i petlja završava.

fgets()

Funkcija fgets() slična je funkciji gets() i izvodi unos redak po redak iz datoteke. Jedan poziv fgets() će pročitati jedan red. U tom slučaju ne možete pročitati cijeli redak, već samo dio od početka. parametri fgets() izgledaju ovako:
fgets (niz_znakova, broj_čitanja_znakova, pokazivač_na_datoteku)

Na primjer:
fgets(str, 50, moja datoteka)

Ovaj poziv funkcije pročitat će iz datoteke povezane s pokazivačem myfile jedan cijeli redak teksta ako je njegova duljina manja od 50 znakova, uključujući znak "\n", koji će funkcija također pohraniti u polje. Posljednji (50.) element niza str bit će znak "\0" koji dodaje fgets(). Ako je niz dulji, funkcija će pročitati 49 znakova i napisati "\0" na kraju. U ovom slučaju, "\n" neće biti sadržan u redu za čitanje.

#uključi #define N 80 main () ( FILE * file; char arr[ N] ; file = fopen ( "fscanf.txt", "r" ) ; while (fgets (arr, N, file) != NULL) printf (" %s" , arr) ; printf (" \n") ; fclose(datoteka); )

U ovom programu, za razliku od prethodnog, podaci se čitaju red po red u polje arr. Kada se pročita sljedeći redak, prethodni se gubi. Funkcija fgets() vraća NULL ako ne može pročitati sljedeći redak.

getc() ili fgetc()

Funkcija getc() ili fgetc() (obje rade) omogućuje vam da dobijete sljedeći pojedinačni znak iz datoteke.

while ((arr[ i] = fgetc (file) ) != EOF) ( if (arr[ i] == " \n") (arr[i] = " \0 " ; printf("%s \n", arr) ; i = 0; ) inače i++; )arr[i] = " \0 " ; printf("%s \n", arr) ;

Primjer koda prikazuje podatke iz datoteke na zaslonu.

Zapisivanje u tekstualnu datoteku

Baš kao i ulaz, izlaz u datoteku može biti različit.

  • Formatirani izlaz. Funkcija fprintf (indeks_datoteke, niz_formata, varijable) .
  • Ispis post-by-line. Funkcija fputs(string, file_pointer) .
  • Ispis znak po znak. Funkcija fputc() ili putc(symbol, file_pointer) .

Ispod su primjeri koda koji koriste tri metode ispisivanja podataka u datoteku.

Upisivanje polja jedne strukture u svaki red datoteke:

datoteka = fopen ("fprintf.txt" , "w" ) ; while (scanf ("%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( fprintf (datoteka, " %s %u %.2f \n", trgovina[ i].naziv, trgovina[ i].količina, trgovina[ i].cijena) ; i++; )

Ispis redak po redak u datoteku (fputs(), za razliku od samog puts(), ne stavlja “\n” na kraj retka):

dok (dobiva (arr) != NULL) ( fputs (arr, datoteka); fputs (" \n", datoteka); )

Primjer ispisa znak po znak:

while ((i = getchar () ) != EOF) putc (i, datoteka) ;

Čitanje iz binarne datoteke i pisanje u nju

Možete raditi s datotekom ne kao nizom znakova, već kao nizom bajtova. U principu, nije moguće raditi s netekstualnim datotekama na bilo koji drugi način. Međutim, na ovaj način možete čitati i pisati u tekstualne datoteke. Prednost ove metode pristupa datoteci je brzina čitanja i pisanja: značajan blok informacija može se čitati/pisati u jednom pristupu.

Prilikom otvaranja datoteke za binarni pristup, drugi parametar fopen() je niz "rb" ili "wb".

Tema rada s binarnim datotekama prilično je složena i zahtijeva posebnu lekciju za proučavanje. Ovdje će biti navedene samo značajke funkcija čitanja i pisanja u datoteku, koja se smatra nizom bajtova.

Funkcije fread() i fwrite() uzimaju kao parametre:

  1. adresu memorijskog područja gdje se podaci upisuju ili čitaju,
  2. veličina jedne date bilo koje vrste,
  3. količina pročitanih podataka navedene veličine,
  4. indeks datoteke.

Ove funkcije vraćaju broj uspješno pročitanih ili zapisanih podataka. Oni. možete "narediti" čitanje 50 podatkovnih elemenata, ali primiti samo 10. Neće biti pogreške.

Primjer korištenja funkcija fread() i fwrite():

#uključi #uključi main () (DATOTEKA * datoteka; char shelf1[ 50], shelf2[ 100] ; int n, m; file = fopen ("shelf1.txt", "rb") ; n= fread (shelf1, sizeof (char) , 50 , datoteka) ; fclose (datoteka) ; datoteka = fopen ("shelf2.txt" , "rb" ) ; m= fread (shelf2, sizeof (char) , 50 , file) ; fclose (datoteka) ; shelf1[ n] = " \0 " ; polica2[m] = " \n"; polica2[ m+ 1 ] = " \0 " ; datoteka = fopen ("shop.txt" , "wb" ) ; fwrite (strcat (shelf2, shelf1) , sizeof (char) , n+ m, file) ; fclose(datoteka); )

Ovdje se pokušava pročitati 50 znakova iz prve datoteke. n pohranjuje broj stvarno pročitanih znakova. Vrijednost n može biti 50 ili manje. Podaci su postavljeni u nizu. Ista stvar se događa s drugom datotekom. Zatim se prvi redak dodaje drugom, a podaci se ubacuju u treću datoteku.

Rješavanje problema

  1. Napišite program koji od korisnika traži naziv (adresu) tekstualne datoteke, zatim je otvara i broji broj znakova i redaka u njoj.
  2. Napišite program koji upisuje u datoteku podatke primljene iz druge datoteke i izmijenjene na neki način prije pisanja. Svaki redak podataka dobivenih iz datoteke mora se uklopiti u strukturu.

Zadnja izmjena: 31.10.2015

Postoje dvije klase dizajnirane za rad s direktorijima u System.IO imenskom prostoru: Directory i DirectoryInfo.

Klasa imenika

Klasa Imenik pruža niz statičkih metoda za upravljanje imenicima. Neke od ovih metoda:

    CreateDirectory(path) : stvara direktorij na navedenoj stazi

    Delete(path) : briše direktorij na navedenoj stazi

    Exists(path) : Određuje postoji li direktorij na navedenoj stazi. Ako postoji, vraća se true, ako ne postoji, tada se vraća false

    GetDirectories(path) : Dobiva popis direktorija u putu direktorija

    GetFiles(path) : dobiva popis datoteka u putanji direktorija

    Premjesti(izvorniDirName, destDirName): pomiče imenik

    GetParent(path) : Dohvaćanje nadređenog direktorija

ImenikInfo klasa

Ova klasa pruža funkcionalnost za stvaranje, brisanje, premještanje i druge operacije imenika. U mnogočemu je sličan imeniku. Neka od njegovih svojstava i metoda:

    Create() : Stvara direktorij

    CreateSubdirectory(path) : Stvara poddirektorij na navedenoj stazi

    Delete() : briše direktorij

    Svojstvo Exists: određuje postoji li direktorij

    GetDirectories() : dobiva popis direktorija

    GetFiles() : dobiva popis datoteka

    MoveTo(destDirName) : Premješta direktorij

    Nadređeno svojstvo: dobivanje nadređenog imenika

    Svojstvo korijena: dobivanje korijenskog direktorija

Pogledajmo primjere korištenja ovih klasa

Dohvaćanje popisa datoteka i poddirektorija

string dirName = "C:\\"; if (Directory.Exists(dirName)) ( Console.WriteLine("Subdirectories:"); string dirs = Directory.GetDirectories(dirName); foreach (string s in dirs) ( Console.WriteLine(s); ) Console.WriteLine( ); Console.WriteLine("Datoteke:"); string files = Directory.GetFiles(dirName); foreach (string s u datotekama) ( Console.WriteLine(s); ) )

Obratite pažnju na korištenje kosih crta u nazivima datoteka. Ili koristimo dvostruku kosu crtu: "C:\\" ili jednu kosu crtu, ali tada stavljamo znak @ ispred cijelog puta: @"C:\Program Files"

Izrada imenika

put niza = @"C:\SomeDir"; string subpath = @"program\avalon"; ImenikInfo dirInfo = novi ImenikInfo(staza); if (!dirInfo.Postoji) ( dirInfo.Create(); ) dirInfo.CreateSubdirectory(podput);

Prvo provjeravamo postoji li takav direktorij, jer ako postoji, neće ga biti moguće kreirati, a aplikacija će izbaciti pogrešku. Kao rezultat, dobit ćemo sljedeću stazu: "C:\SomeDir\program\avalon"

Dobivanje informacija o imeniku

string dirName = "C:\\Programske datoteke"; ImenikInfo dirInfo = novi ImenikInfo(dirName); Console.WriteLine($"Ime direktorija: (dirInfo.Name)"); Console.WriteLine($"Puni naziv direktorija: (dirInfo.FullName)"); Console.WriteLine($"Vrijeme stvaranja imenika: (dirInfo.CreationTime)"); Console.WriteLine($"Korijenski direktorij: (dirInfo.Root)");

Uklanjanje imenika

Ako jednostavno primijenimo metodu Delete na nepraznu mapu koja sadrži neke datoteke ili poddirektorije, aplikacija će izbaciti pogrešku. Stoga, metodi Delete moramo proslijediti dodatni parametar boolean tipa koji će naznačiti da se mapa treba izbrisati sa svim svojim sadržajem:

String dirName = @"C:\SomeFolder"; pokušaj ( DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Directory deleted"); ) catch (Exception ex) ( Console.WriteLine(ex.Message); )

String dirName = @"C:\SomeFolder"; Imenik.Delete(dirName, istina);

Premještanje imenika

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

Kod selidbe moramo voditi računa da novi imenik u koji želimo premjestiti sav sadržaj starog imenika ne smije postojati.