Rad sa tekstualnim fajlovima u C++.
Postoje dvije glavne vrste datoteka: tekstualni i binarni. Datoteke omogućavaju korisniku da čita velike količine podataka direktno sa diska bez da ih ukuca sa tastature.
Tekst nazivaju se datoteke koje se sastoje od bilo kojeg karaktera. Oni su organizirani u redove, od kojih se svaki završava znakom na kraju reda. Kraj samog fajla je označen simbolom "kraj datoteke". Prilikom pisanja informacija u tekstualnu datoteku, koja se može vidjeti pomoću bilo kojeg uređivača teksta, svi podaci se pretvaraju u tip znakova i pohranjuju u obliku znakova.
AT binarni U datotekama se informacije čitaju i zapisuju u obliku blokova određene veličine, u koje se mogu pohraniti podaci bilo koje vrste i strukture.
Za rad sa fajlovima, specijal tipovi podataka, zvao potoci. Flow ifstream koristi se za rad sa datotekama u načinu čitanja, i van struje u režimu snimanja. Stream se koristi za rad sa datotekama u načinu pisanja i čitanja. fstream.
U C++ programima, kada radite sa tekstualnim datotekama, potrebno je uključiti iostream i fstream biblioteke.
To zapiši podatke u tekstualnu datoteku, morate:
opisati varijablu tipa toka.
izlazne informacije u datoteku.
obavezno zatvorite fajl.
Za čitanja podatke iz tekstualne datoteke, morate:
opisati varijablu tipa ifstream.
otvorite datoteku koristeći funkciju otvaranja.
zatvorite fajl.
Snimanje informacije u tekstualnu datoteku
Kao što je ranije spomenuto, da biste počeli raditi s tekstualnom datotekom, morate deklarirati varijablu tipa ofstream. Na primjer, ovako:
Varijabla F će biti kreirana za upisivanje informacija u datoteku.
Sljedeći korak je otvaranje datoteke za pisanje. Općenito, operator otvaranja toka će izgledati ovako:
F. open("file", mod);
Ovdje je F varijabla deklarirana kao offstream,
file - puno ime datoteke na disku,
mode - način rada sa otvorenim fajlom.
Imajte na umu da kada navodite puno ime datoteke, morate staviti dvostruku kosu crtu. Na primjer, puno ime datoteke noobs.txt koja se nalazi u mapi igre na D: pogonu morat će biti napisano ovako:
D:\\game\\noobs.txt.
Datoteka se može otvoriti na jedan od sljedećih načina:
ios::in - otvori datoteku u načinu čitanja podataka, ovaj način je zadani način za ifstream streamove;
ios::out - otvori datoteku u režimu pisanja podataka (u ovom slučaju, informacije o postojećoj datoteci su uništene), ovaj režim je podrazumevani režim za streamove;
ios::app - otvorite datoteku u načinu upisivanja podataka do kraja datoteke;
ios::ate - prelazak na kraj već otvorenog fajla;
ios::trunc - obrišite datoteku, isto se dešava u ios::out modu;
ios::nocreate - ne otvaraj datoteku ako ne postoji;
ios::noreplace - Ne otvaraj postojeći fajl.
Parametar moda može biti odsutan, u kom slučaju se datoteka otvara u zadanom načinu za ovaj stream.
Nakon uspješnog otvaranja datoteke (u bilo kojem načinu), F varijabla će pohraniti true, a u suprotnom false. Ovo će provjeriti ispravnost operacije otvaranja datoteke.
Možete otvoriti datoteku (uzmimo D:\\game\\noobs.txt kao primjer) u načinu pisanja koristeći jedan od sljedećih metoda:
// prvi način
offstream F;
F.open("D:\\game\\noobs.txt", ios::out);
//drugi način, ios::out mod je zadani način
// za protokvan struje
offstream F;
//treći način kombinuje opis varijable i tip toka
//i otvorimo datoteku u jednoj izjavi
ofstream F("D:\\game\\noobs.txt", ios::out);
Nakon otvaranja datoteke u načinu pisanja, kreirat će se prazna datoteka u koju se mogu upisati informacije.
Ako želite da otvorite postojeću datoteku u režimu pre pisanja, koristite ios::app kao režim.
Nakon otvaranja datoteke u načinu pisanja, možete u nju pisati na isti način kao na ekranu, samo umjesto standardnog izlaznog uređajacoutmorate navesti ime otvorene datoteke.
Na primjer, za pisanje varijable a u tok F, izlazni izraz bi bio:
Za sekvencijalno ispis varijabli b, c, d u tok G, izlazni izraz postaje:
G<
Tok se zatvara pomoću operatora:
PRIMJER:
Kreirajte tekstualni fajl D:\\game\\noobs.txt i u njega upišite n realnih brojeva.
#include "stdafx.h"
#include
#include
#include
korištenje imenskog prostora std;
int main()
setlocale(LC_ALL, "RUS");
int i, n;
duplo a;
//opisuje tok za pisanje podataka u datoteku
van struje f;
//otvori datoteku u načinu pisanja,
//modeios:: vaninstaliran prema zadanim postavkama
f.open("D:\\game\\noobs.txt", ios::out);
//unesite broj realnih brojeva
cout<<" n="; cin>> n;
//petlja za unos realnih brojeva
//i zapisivanje u datoteku
za (i=0; i
cout<<"a=";
//unos broja
cin>>a;
//zatvaranje streama
f.close();
system("pauza");
return 0;
_______________________________________________________________
Da biste pročitali informacije iz tekstualnog fajla, potrebno je deklarisati varijablu tipa ifstream. Nakon toga morate otvoriti datoteku za čitanje pomoću operatora otvoren. Ako se varijabla zove F, tada će prve dvije izjave biti sljedeće:
F.open("D:\\game\\noobs.txt", ios::in);
Nakon otvaranja datoteke u načinu čitanja, možete čitati informacije iz nje na isti način kao s tastature, samo umjestocinnavedite ime toka iz kojeg će se podaci čitati.
Na primjer, za čitanje iz toka F u varijablu a, input izraz bi izgledao ovako:
Dva broja u uređivaču teksta smatraju se odvojenima ako između njih postoji barem jedan znak: razmak, tabulator, znak na kraju reda. Dobro je ako programer unaprijed zna koliko i koje vrijednosti treba pohraniti u tekstualnu datoteku. Međutim, često je tip vrijednosti pohranjenih u datoteci jednostavno poznat, a njihov broj može varirati. Da biste riješili ovaj problem, potrebno je da čitate vrijednosti iz datoteke jednu po jednu, a prije svakog čitanja provjerite da li je došlo do kraja datoteke. Za to postoji funkcija F. eof().
Ovdje je F ime toka, funkcija vraća logičku vrijednost: true ili false, ovisno o tome da li je dostignut kraj datoteke. Stoga se petlja za čitanje sadržaja cijele datoteke može napisati ovako:
//organizirati za čitanje vrijednosti iz datoteke, izvršenje
//petlja će se prekinuti kada dođemo do kraja datoteke,
//u ovom slučaju F.eof() će vratiti true
dok (!F.eof())
PRIMJER:
Realni brojevi se pohranjuju u tekstualnu datoteku D:\\game\\noobs.txt, prikažite ih na ekranu i izračunajte njihov broj.
#include "stdafx.h"
#include
#include
#include
#include
korištenje imenskog prostora std;
int main()
setlocale(LC_ALL, "RUS");
intn=0;
float a;
fstream F;
//otvorimo datoteku u načinu čitanja
F.open("D:\\game\\noobs.txt");
//ako je datoteka ispravno otvorena, onda
//petlja za čitanje vrijednosti iz datoteke; izvođenje petlje će biti prekinuto,
// kada dođemo do kraja datoteke, u kom slučaju će F.eof() vratiti true.
dok (!F.eof())
//čitanje sljedeće vrijednosti iz toka F u varijablu a
F>>a;
//izlaz vrijednosti varijable a na ekran
//povećavamo broj pročitanih brojeva
//zatvaranje streama
f.close();
//unos broja pročitanih brojeva na ekranu
cout<<"n="<
//ako je datoteka pogrešno otvorena, onda izlaz
//poruke o nepostojanju takve datoteke
else cout<<" Файл не существует"<
system("pauza");
return 0;
C++. Obrada binarnih datoteka
Prilikom pisanja informacija u binarnu datoteku, znakovi i brojevi se zapisuju kao niz bajtova.
To zapiši podatke u binarnu datoteku, potrebno je:
deklarirajte varijablu datoteke tipa FAIL * koristeći izraz FILE *filename;. Ovdje naziv datoteke je ime varijable gdje će biti pohranjen pokazivač na datoteku.
zapišite informacije u datoteku koristeći funkciju fwrite
To razmisli z podataka iz binarne datoteke, morate:
opišite varijablu tipa FILE *
otvorite datoteku sa fopen funkcijom
zatvorite datoteku sa funkcijom fclose
Osnovne funkcije potrebne za rad s binarnim datotekama.
Za otkrića datoteka, funkcija fopen je namijenjena.
FILE *fopen(const *filename, const char *mode)
Ovdje filename je string koji pohranjuje puno ime datoteke koja se otvara, mode je niz koji definira način rada sa datotekom; moguće su sljedeće vrijednosti:
"rb" - otvaranje binarne datoteke u načinu čitanja;
"wb" - kreirati binarnu datoteku za pisanje; ako postoji, njen sadržaj se briše;
"ab" - kreirajte ili otvorite binarnu datoteku za dodavanje na kraj datoteke;
"rb+" - otvara postojeću binarnu datoteku u načinu čitanja i pisanja;
"wb+" - otvara binarnu datoteku u načinu čitanja i pisanja, postojeći fajl se briše;
"ab+" - Otvara se ili kreira binarna datoteka kako bi se ispravile postojeće informacije i dodale nove informacije na kraj datoteke.
Funkcija vraća NULL vrijednost u varijablu datoteke f ako datoteka nije uspješno otvorena. Nakon otvaranja datoteke, njen 0-ti bajt je dostupan, pokazivač datoteke je 0, čija se vrijednost pomjera za pročitani (upisani) broj bajtova dok se čita ili upisuje. Trenutna vrijednost pokazivača datoteke je broj bajta iz kojeg će se izvršiti operacija čitanja ili pisanja.
Za zatvaranje datoteku, funkcija fclose je namijenjena
int fclose(FILE *ime datoteke);
Vraća 0 ako je datoteka uspješno zatvorena, NULL u suprotnom.
Funkcija uklanjanja je za odstranjivanje datoteke.
int remove(const char *ime datoteke);
Ova funkcija uklanja datoteku pod nazivom filenema s diska. Datoteka koju treba izbrisati mora biti zatvorena. Funkcija vraća vrijednost različitu od nule ako se datoteka ne može izbrisati.
Za preimenovanje datoteke, funkcija preimenovanja je namijenjena:
int rename(const char *oldfilename, const char *newfilename);
Prvi parametar je staro ime datoteke, drugi je novi. Vraća 0 nakon uspješnog završetka programa.
Čitanje iz binarne datoteke se radi pomoću funkcije fread:
fread(void *ptr, veličina, n, FILE *ime datoteke);
Funkcija fread čita n elemenata veličine veličine iz naziva datoteke u ptr niz. Funkcija vraća broj pročitanih elemenata. Nakon čitanja iz datoteke, njen pokazivač se pomjera za n*veličine bajtova.
Snimanje u binarnu datoteku se vrši pomoću funkcije fwrite:
fwrite(const void *ptr, veličina, n, FILE *ime datoteke);
Funkcija fwrite upisuje n elemenata veličine u ime datoteke iz ptr niza. Funkcija vraća broj upisanih elemenata. Nakon što se informacija upiše u datoteku, pokazivač se pomjera za n*veličine bajtova.
Za kontrola kraja datoteke postoji feof funkcija:
int feof(FILE *ime datoteke);
Vraća vrijednost različitu od nule ako se dostigne kraj datoteke.
PRIMJER:
Kreirajte binarni fajl D:\\game\\noobs.dat i u njega upišite cijeli broj n i n realnih brojeva.
#include "stdafx.h"
#include
korištenje imenskog prostora std;
int main()
setlocale(LC_ALL, "RUS");
int n, i;
duplo a;
// kreirati binarnu datoteku u načinu pisanja
f=fopen("D:\\game\\noobs.dat", "wb");
// unos brojevin
cout<<"n="; cin>>n;
fwrite(&n, sizeof(int), 1, f);
//petlja za unos n realnih brojeva
za (i=0; i
//unesite sljedeći realni broj
cout<<"a=";
cin>>a;
//upisuje realni broj u binarnu datoteku
fwrite(&a, sizeof(double), 1, f);
// zatvori fajl
fclose(f);
system("pauza");
return 0;
PRIMJER:
Prikaži sadržaj binarne datoteke D:\\game\\noobs.dat kreirane u prethodnom zadatku
#include "stdafx.h"
#include
korištenje imenskog prostora std;
int main()
setlocale(LC_ALL, "RUS");
int n, i;
duplo *a;
FILE *f; //opišemo varijablu datoteke
//otvaranje postojeće binarne datoteke u načinu čitanja
//čitaj jedan cijeli broj iz datoteke u varijablu n
//izlaz n na ekran
cout<<"n="<
//dodijelimo memoriju za niz od n brojeva
a=novi dupli[n];
//čitanje n realnih brojeva iz datoteke u niz a
//izlaz niza na ekran
za (i=0; i
cout<
// zatvori fajl
fclose(f);
system("pauza");
return 0;
Binarno- sekvencijalna struktura podataka, nakon otvaranja datoteke, dostupan je prvi bajt pohranjen u njoj. Možete sekvencijalno pisati ili čitati podatke iz datoteke. Pretpostavimo da trebate izbrojati petnaesti broj, a zatim prvi. Sa serijskim pristupom to se može učiniti na sljedeći način:
int n, i;
duplo a;
FILE *f;
f=fopen("D:\\game\\noobs.dat", "rb");
za (i=0; i<15; i++)
fclose(f);
f=fopen("D:\\game\\noobs.dat", "rb");
fread(&a, sizeof(double), 1, f);
fclose(f);
Kao što vidite, čitanje brojeva iz datoteke, a zatim ponovno otvaranje datoteke nije najpogodniji način. Mnogo je zgodnije koristiti funkciju fseek za pomicanje pokazivača datoteke na dati bajt.
int fseek(FILE *ime datoteke, dugi int pomak, int porijeklo);
Funkcija postavlja pokazivač na trenutnu poziciju datoteke F u skladu sa vrijednošću početka i pomaka. Parametar pomaka jednak je broju bajtova za koji će se pokazivač datoteke pomjeriti u odnosu na ishodište specificirano parametrom porijekla. Vrijednost parametra porijekla mora biti jedna od sljedećih vrijednosti za pomak, definiranih u zaglavlju stdio.h:
SEEK_SET - od početka fajla;
SEEK_CUR - sa trenutne pozicije;
SEEK_END - sa kraja fajla.
Funkcija vraća nulu ako je operacija uspješna, različitu od nule ako pomak ne uspije.
Funkcija fseek zapravo implementira direktan pristup bilo kojoj vrijednosti u datoteci. Trebate samo znati lokaciju (broj bajta) vrijednosti u datoteci. Razmotrite upotrebu direktnog pristupa u binarnim datotekama koristeći primjer rješavanja sljedećeg problema.
PRIMJER
U binarnoj datoteci D:\\game\\noobs.dat kreiranoj ranije, zamijenite najveći i najmanji realni broj.
Algoritam za rješavanje problema sastoji se od sljedećih koraka:
čitanje realnih vrijednosti iz datoteke u niz a.
pretražite u nizu a maksimalne (max) i minimalne (min) vrijednosti i njihove brojeve (imax, imin).
pomeranje pokazivača fajla na maksimalnu vrednost i pisanje min.
pomeranje pokazivača fajla na minimalnu vrednost i pisanje max.
Ispod je tekst programa za rješavanje problema s komentarima.
#include "stdafx.h"
#include
korištenje imenskog prostora std;
int main()
setlocale(LC_ALL, "RUS");
int n, i, imax, imin;
duplo *a, max, min;
FILE *f;
//otvaranje datoteke u načinu čitanja/pisanja
f=fopen("D:\\game\\noobs.dat", "rb+");
//čitanje iz datoteke u varijablu n broj
//realni brojevi u datoteci
fread(&n, sizeof(int), 1, f);
cout<<"n="<
//dodijeliti memoriju za pohranjivanje realnih brojeva,
//koji će biti pohranjen u nizu a
a=novi dupli[n];
//čitanje iz datoteke u niz i realne brojeve
fread(a, sizeof(double), n, f);
//tražimo maksimalne i minimalne elemente
//u nizu a i njihovim indeksima
za (imax=imin=0, max=min=a, i=1; i
ako (a[i]>max)
max=a[i];
ako (a[i]
min=a[i];
// kreće se pokazivač to maksimum element
fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET);
//snimanje min umjesto maksimalnog elementa datoteke
fwrite(&min, sizeof(double), 1, f);
// kreće se pokazivač to minimum element
fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET);
//zabilježite maksimum umjesto minimalnog elementa datoteke
fwrite(&max, sizeof(double), 1, f);
//zatvaranje fajla
fclose(f);
// slobodna memorija
obriši[ ]a;
system("pauza");
Tekstualne datoteke
Razmotrimo rad sa tekstualnom datotekom u C koristeći primjer. Kreirajte tekstualnu datoteku na disku C pod nazivom TextFile.txt. Unesite sljedeće redove u ovu datoteku:
Niz_1 123 Niz_11, 456
String_2
String_3
Sačuvajte fajl.
A ovo je kod za C program koji otvara naš fajl i čita redove iz njega:
/* *Autor: @author Subbotin B.P..h> #include
Da otvorite tekstualnu datoteku u C, koristite funkciju fopen:
FILE *pTextFile = fopen("C:\\TextFile.txt", "r");
Prvi argument funkcije fopen ukazuje na datoteku, a drugi kaže da je datoteka otvorena za čitanje iz nje.
Čitamo redove koristeći fgets funkciju:
fgets(cArray, LEN, pTextFile);
Prvi argument funkcije fgets ukazuje na niz znakova u koji će primljeni nizovi biti pohranjeni, drugi argument je maksimalan broj znakova za čitanje, treći je naš fajl.
Nakon što završite rad sa fajlom, morate ga zatvoriti:
fclose(pTextFile);
Dobijamo:
Prolaze i ruska slova u redovima.
Inače, napravio sam ovaj program u Eclipse-u. Možete vidjeti kako raditi sa C/C++ u Eclipseu.
Dakle, otvorili smo i pročitali podatke iz tekstualne datoteke.
Sada naučimo kako programski kreirati tekstualnu datoteku i zapisati podatke u nju.
/* Autor: @author Subbotin B.P..h> #include
Kreirajte tekstualnu datoteku da u nju upišete podatke:
FILE *pTextFile = fopen("C:\\TextFileW.txt", "w");
ako datoteka već postoji, biće otvorena i svi podaci će biti izbrisani iz nje.
C-string cString i broj nVal program upisuje u tekstualnu datoteku. cNewLine je samo prijelom reda.
Zapisujemo podatke u tekstualnu datoteku koristeći fprintf funkciju:
fprintf(pTextFile, "%s%c", cString, cNewLine);
prvi argument ovdje je naš fajl, drugi je niz formata, treći ili više je broj argumenata potrebnih za ovaj format.
Radi lakšeg rukovanja, informacije u uređajima za pohranu pohranjuju se u obliku datoteka.
Datoteka je imenovana oblast vanjske memorije koja je dodijeljena za pohranjivanje niza podataka. Podaci sadržani u datotekama su najrazličitije prirode: programi na algoritamskom ili mašinskom jeziku; početni podaci za rad programa ili rezultati izvođenja programa; proizvoljni tekstovi; grafike itd.
Direktorij (fascikla, direktorij) - imenovana kolekcija bajtova na mediju za pohranu koji sadrži nazive poddirektorija i datoteka, koji se koriste u sistemu datoteka za pojednostavljenje organizacije datoteka.
sistem podataka je funkcionalni dio operativnog sistema koji pruža operacije nad datotekama. Primeri sistema datoteka su FAT (FAT - Tabela alokacije datoteka, tabela alokacije datoteka), NTFS, UDF (koristi se na CD-ovima).
Postoje tri glavne verzije FAT-a: FAT12, FAT16 i FAT32. Razlikuju se po bitnosti zapisa u strukturi diska, tj. broj bitova dodijeljenih za pohranjivanje broja klastera. FAT12 se uglavnom koristi za flopi diskove (do 4 KB), FAT16 za male diskove, FAT32 za FLASH diskove velikog kapaciteta (do 32 GB).
Razmotrite strukturu sistema datoteka koristeći FAT32 kao primjer.
FAT32 struktura datoteke
Eksterni memorijski uređaji u sistemu FAT32 nisu bajt, već blok adresiranje. Informacije se upisuju na eksterni memorijski uređaj u blokovima ili sektorima.
Sektor - minimalna adresabilna jedinica za skladištenje informacija na eksternim uređajima za skladištenje. Tipično, veličina sektora je fiksna na 512 bajtova. Da bi se povećao adresni prostor eksternih memorijskih uređaja, sektori se kombinuju u grupe koje se nazivaju klasteri.
Klaster je asocijacija više sektora, koji se mogu smatrati nezavisnom jedinicom sa određenim svojstvima. Glavno svojstvo klastera je njegova veličina, mjerena brojem sektora ili brojem bajtova.
FAT32 sistem datoteka ima sljedeću strukturu.
Klasteri koji se koriste za pisanje fajlova su numerisani počevši od 2. U pravilu, klaster #2 koristi osnovni direktorijum, a počevši od klastera #3, pohranjuje se niz podataka. Sektori koji se koriste za pohranjivanje informacija iznad korijenskog direktorija nisu grupirani.
Minimalna veličina datoteke na disku je 1 klaster.
Sektor za pokretanje počinje sa sljedećim informacijama:
- EB 58 90 - bezuslovna grana i potpis;
- 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
- 00 02 - broj bajtova u sektoru (obično 512);
- 1 bajt - broj sektora u klasteru;
- 2 bajta - broj rezervnih sektora.
Osim toga, sektor za pokretanje sadrži sljedeće važne informacije:
- 0x10 (1 bajt) – broj FAT tabela (obično 2);
- 0x20 (4 bajta) - broj sektora na disku;
- 0x2C (4 bajta) – broj klastera korijenskog direktorija;
- 0x47 (11 bajtova) – oznaka volumena;
- 0x1FE (2 bajta) - Potpis sektora za pokretanje (55 AA).
Sektor informacija o sistemu datoteka sadrži:
- 0x00 (4 bajta) – potpis (52 52 61 41 );
- 0x1E4 (4 bajta) – potpis (72 72 41 61 );
- 0x1E8 (4 bajta) – broj slobodnih klastera, -1 ako nije poznato;
- 0x1EC (4 bajta) – broj posljednjeg snimljenog klastera;
- 0x1FE (2 bajta) - potpis (55 AA).
FAT tabela sadrži informacije o stanju svakog klastera na disku. Donja 2 bajta FAT tabele pohranjuju F8 FF FF 0F FF FF FF FF (odgovara stanju klastera 0 i 1, fizički odsutan). Nadalje, stanje svakog klastera sadrži broj klastera u kojem se nastavlja trenutni fajl ili sljedeće informacije:
- 00 00 00 00 – klaster je slobodan;
- FF FF FF 0F je kraj trenutnog fajla.
- 8 bajtova - naziv datoteke;
- 3 bajta - ekstenzija datoteke;
Korijenski direktorij sadrži skup 32-bitnih zapisa informacija za svaki fajl koji sadrži sljedeće informacije:
Kada radite sa dugim nazivima datoteka (uključujući ruska imena), naziv datoteke je kodiran u UTF-16 sistemu kodiranja. U ovom slučaju, 2 bajta se dodjeljuju za kodiranje svakog znaka. U ovom slučaju, naziv datoteke je napisan u obliku sljedeće strukture:
- 1 bajtova sekvenca;
- 10 bajtova sadrži donjih 5 znakova imena datoteke;
- 1 bajt atribut;
- 1 bajt rezerviran;
- 1 bajt - kontrolna suma DOS imena;
- 12 bajtova sadrže donja 3 znaka imena datoteke;
- 2 bajta – broj prvog klastera;
- preostali znakovi dugog imena.
Rad sa datotekama u C
Za programera, otvorena datoteka je predstavljena kao niz podataka koji se čitaju ili pišu. Kada se datoteka otvori, ona je povezana sa I/O tok. Izlazne informacije se upisuju u tok, ulazne informacije se čitaju iz toka.
Kada se tok otvori za I/O, on je povezan sa standardnom strukturom tipa FILE, koja je definirana u stdio.h. Struktura FILE sadrži potrebne informacije o datoteci.
Otvaranje datoteke se vrši pomoću fopen() funkcije, koja vraća pokazivač na strukturu tipa FILE, koja se može koristiti za naredne operacije na datoteci.
FILE *fopen(ime, tip);
ime je ime datoteke koja se otvara (uključujući putanju),
tip je pokazivač na niz znakova koji definiraju kako se pristupa datoteci:
- "r" - otvori datoteku za čitanje (datoteka mora postojati);
- "w" - otvara praznu datoteku za pisanje; ako datoteka postoji, njen sadržaj se gubi;
- "a" - otvoren fajl za pisanje do kraja (za dodavanje); datoteka se kreira ako ne postoji;
- "r+" - otvorena datoteka za čitanje i pisanje (datoteka mora postojati);
- "w+" - otvara praznu datoteku za čitanje i pisanje; ako datoteka postoji, njen sadržaj se gubi;
- "a+" - otvorite datoteku za čitanje i dodavanje, ako datoteka ne postoji, kreira se.
Povratna vrijednost je pokazivač na otvoreni tok. Ako se pronađe greška, vraća se NULL.
Funkcija fclose() zatvara tok ili tokove povezane s datotekama otvorenim pomoću fopen(). Tok koji treba zatvoriti je određen argumentom funkcije fclose().
Povratna vrijednost: vrijednost 0 ako je stream uspješno zatvoren; EOF konstanta ako je došlo do greške.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include
int main() (
FILE *fp;
char name = "my.txt" ;
if ((fp = fopen(ime, "r" )) == NULL )
{
printf( "Nije moguće otvoriti fajl");
getchar();
return 0;
}
// otvaranje datoteke uspješno
... // potrebne radnje na podacima
fclose(fp);
getchar();
return 0;
}
Čitanje znaka iz datoteke:
char fgetc(stream);
Argument funkcije je pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka. Ako se dostigne kraj datoteke ili dođe do greške, vraća se EOF konstanta.
Upisivanje karaktera u datoteku:
fputc(znak, tok);
Argumenti funkcije su znak i pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka.
Funkcije fscanf() i fprintf() slične su funkcijama scanf() i printf(), ali rade na datotekama podataka i imaju pointer kao prvi argument.
fscanf(stream, "InputFormat" , args);
Za programera, otvorena datoteka je predstavljena kao niz podataka koji se čitaju ili pišu. Kada se datoteka otvori, ona je povezana sa I/O tok . Izlazne informacije se upisuju u tok, ulazne informacije se čitaju iz toka.
Kada se tok otvori za I/O, on je povezan sa standardnom strukturom tipa FILE, koja je definirana u stdio.h. Struktura FILE sadrži potrebne informacije o datoteci.
Otvaranje datoteke se vrši pomoću fopen() funkcije, koja vraća pokazivač na strukturu tipa FILE, koja se može koristiti za naredne operacije s datotekom.
FILE *fopen(ime, tip);
ime je ime datoteke koja se otvara (uključujući putanju),
type - pokazivač na niz znakova koji definiraju kako se pristupa datoteci:
· "r" - otvori datoteku za čitanje (datoteka mora postojati);
· "w" - otvara praznu datoteku za pisanje; ako datoteka postoji, njen sadržaj se gubi;
· "a" - otvoren fajl za pisanje do kraja (za dodavanje); datoteka se kreira ako ne postoji;
· "r+" - otvara fajl za čitanje i pisanje (fajl mora postojati);
· "w+" - otvara praznu datoteku za čitanje i pisanje; ako datoteka postoji, njen sadržaj se gubi;
· "a+" - otvara fajl za čitanje i dodavanje, ako fajl ne postoji, kreira se.
Povratna vrijednost je pokazivač na otvoreni tok. Ako se pronađe greška, vraća se NULL.
Funkcija fclose() zatvara tok ili tokove povezane s datotekama otvorenim pomoću fopen(). Tok koji treba zatvoriti je određen argumentom funkcije fclose().
Povratna vrijednost: vrijednost 0 ako je stream uspješno zatvoren; EOF konstanta ako je došlo do greške.
#include
int main()
char name="my.txt";
if(fp = fopen(ime, "r")!=NULL)
// da li je bilo moguće otvoriti fajl?
... // potrebne radnje na podacima
else printf("Ne mogu otvoriti fajl");
Čitanje znaka iz datoteke:
char fgetc(stream);
Argument funkcije je pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka. Ako se dostigne kraj datoteke ili dođe do greške, vraća se EOF konstanta.
Upisivanje karaktera u datoteku:
fputc(znak, tok);
Argumenti funkcije su znak i pokazivač na tok tipa FILE. Funkcija vraća kod pročitanog znaka.
Funkcije fscanf() i fprintf() slične su funkcijama scanf() i printf(), ali rade na datotekama podataka i imaju pointer kao prvi argument.
fscanf(stream, "Input Format", argumenti);
fprintf(stream, "Output Format", argumenti);
Funkcije fgets() i fputs() su za string I/O, analogne su funkcijama gets() i puts() za rad sa datotekama.
fgets(pokazivač na niz, broj znakova, tok);
Znakovi se čitaju iz toka dok se ne pročita znak novog reda "\n", koji je uključen u string, ili dok kraj toka nije EOF ili dok se ne pročita maksimalan broj znakova. Rezultat se stavlja u string pokazivač i završava nultom karakterom "\0". Funkcija vraća adresu niza.
fputs(Pointer to String, stream);
Kopira string u tok sa trenutne pozicije. Završni null karakter se ne kopira.
Primjer
Unesite broj i sačuvajte ga u s1.txt fajlu. Pročitajte broj iz datoteke s1.txt, povećajte ga za 3 i sačuvajte u s2.txt datoteci.
I/O mehanizam koji je razvio , ne odgovara opšteprihvaćenom objektno orijentisanom stilu programiranja danas, osim toga, aktivno koristi operacije pokazivača, koje se smatraju potencijalno nebezbednim u modernim okruženjima bezbednog izvršavanja koda. Alternativa za razvoj aplikacija je standardni mehanizam I/O klase koji obezbjeđuje standard jezika C++.
Otvaranje fajlova
Najčešće korištene klase su ifstream za čitanje, ofstream za pisanje i fstream za modificiranje datoteka.
Sve navojne I/O klase indirektno su izvedene iz zajedničkog pretka ios-a, u potpunosti nasljeđujući njegovu funkcionalnost. Na primjer, open_mode nabrojani član podataka specificira način otvaranja datoteke, koji je definiran na sljedeći način:
Enum open_mode ( app, binary, in, out, trunc, ate );
Ispod su moguće vrijednosti zastava i njihova namjena.
Na primjer, da biste otvorili datoteku pod nazivom test.txt za čitanje binarnih podataka, napisali biste:
ifstream datoteka; file.open("test.txt", ios::in | ios::binary);
Logički OR operator (|) vam omogućava da sastavite režim sa bilo kojom kombinacijom zastavica. Da prilikom otvaranja datoteke pisanjem ne biste slučajno prepisali postojeći fajl istog imena, morate koristiti sljedeći obrazac:
offstream fajl; file.open("test.txt", ios::out | ios::app);
Pretpostavlja se da je odgovarajući fajl zaglavlja povezan sa projektom:
#include
Da biste provjerili je li datoteka uspješno otvorena, možete koristiti konstrukciju
If (!file) ( // Rukovanje greškom otvaranja datoteke)
Operatori uključivanja i ekstrakcije
Poništeno u klasama rukovanja datotekama uključi operatera (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:
File<< "Это строка текста";
Također možete napisati tekstualni niz u dijelovima:
File<< "Это " << "строка " << "текста";
Naredba endl završava unos u liniji s povratnim znakom:
File<< "Это строка текста" << endl;
Koristeći operator uključivanja, lako je zapisati vrijednosti varijabli ili elemenata niza u datoteku:
Offstream fajl("Temp.txt"); char buff = "Tekstualni niz sadrži varijable"; int vx = 100; float pi = 3,14159; fajl<< buff << endl << vx << endl << pi << endl;
Kao rezultat izvršenja koda, generiraju 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 binarne vrijednosti.
operator ekstrakcije(>>) radi suprotno. Čini se da da biste izdvojili znakove iz datoteke Temp.txt koja je ranije napisana, trebate napisati sljedeći kod:
ifstream fajl("Temp.txt"); char buff; intvx; floatpi; fajl >> buff >> vx >> pi;
Međutim, operator ekstrakcije će se zaustaviti na prvom graničniku (razmak, tabulator ili novi red) na koji naiđe. Dakle, prilikom raščlanjivanja rečenice "Tekstni niz sadrži varijable", samo će riječ "Text" biti upisana u niz buff , razmak se zanemaruje, a riječ "niz" će postati vrijednost cjelobrojne varijable vx i koda izvršenje će se "pokvariti" uz neizbježno kršenje strukture podataka. Zatim, kada govorimo o klasi ifstream, pokazat ćemo kako pravilno organizirati čitanje datoteke iz prethodnog primjera.
ifstream klasa: čitanje datoteka
Kao što naziv implicira, klasa ifstream je dizajnirana za unos toka datoteka. Glavne metode klase su navedene u nastavku. Većina njih je naslijeđena iz istream klase i preopterećena roditeljskom funkcionalnošću. Na primjer, funkcija get, ovisno o parametru poziva, može pročitati ne samo jedan znak, već i blok znakova.
Sada je jasno kako trebate modificirati prethodni primjer tako da korištenje operatora ekstrakcije podataka daje očekivani rezultat:
ifstream fajl("Temp.txt"); char buff; intvx; floatpi; file.getline(buff, sizeof(buff)); datoteka >> vx >> pi:
Getline metoda će pročitati prvi red datoteke do kraja, a >> operator će dodijeliti vrijednosti varijablama.
Sljedeći primjer pokazuje dodavanje podataka u tekstualnu datoteku, a zatim čitanje cijele datoteke. Petlja while (1) se koristi umjesto while(!file2.eof()) iz razloga o kojima se govori u .
#include
Sljedeći primjer se kreće kroz čitanje redova iz datoteke test.txt i njihovo prikazivanje na konzoli.
#include
Ovaj kod pod Windows OS-om također ovisi o prisutnosti znaka za novi red u posljednjem redu datoteke, bilo bi pouzdanije učiniti ovo:
Dok (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }
Eksplicitni pozivi metodama open i close su opcioni. Zaista, pozivanje konstruktora s argumentom omogućava vam da odmah otvorite datoteku, u trenutku kada je kreiran objekt toka datoteke:
ifstream fajl("test.txt");
Umjesto metode close, možete koristiti operator delete, koji će automatski pozvati destruktor objekta datoteke i zatvoriti datoteku. Kod petlje while pruža ispravnu provjeru kraja datoteke.
ofstream klasa: pisanje datoteka
Ofstream klasa je dizajnirana za izlaz podataka iz toka datoteka. Glavne metode ove klase su navedene u nastavku.
Ranije opisani operator uključivanja pogodan je za organiziranje pisanja u tekstualnu datoteku:
Offstream fajl("temp.txt"); if (!file) return; za (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();
Binarnosti
U principu, binarni podaci se serviraju kao tekstualni podaci. Razlika je u tome što ako su binarni podaci zapisani u određenoj logičkoj strukturi, onda se moraju pročitati iz datoteke u varijablu istog tipa strukture.
Prvi parametar metoda upisivanja i čitanja (adresa bloka za upisivanje/čitanje) mora biti tipa pokazivača znakova char *, pa je potrebno eksplicitno konvertovati tip adrese void * strukture. Drugi parametar specificira da binarni blokovi datoteke imaju konstantnu veličinu bajta bez obzira na stvarnu dužinu zapisa. Sljedeći dodatak daje primjer kako kreirati i prikazati podatke u jednostavnoj bilježnici. Zapisi datoteke se zatim uzastopno čitaju i prikazuju na konzoli.
#include
Kao rezultat izvršavanja ovog koda, binarna datoteka Notebook.dat se formira od tri bloka od 80 bajtova svaki (pod pretpostavkom da su znakovi jednobajtni). Naravno, možete koristiti druge metode strujanja i izvršiti bilo koju operaciju na poljima određene strukture podataka.
fstream klasa: slučajni pristup fajlu
Pretpostavimo da je u našoj bilježnici skupljeno 100 unosa, a mi želimo da izbrojimo 50. Naravno, možete organizirati petlju i čitati sve zapise od prvog do zadanog. Očigledno je ciljanije rješenje postaviti pokazivač pozicije pos datoteke direktno na unos 50 i pročitati ga:
ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Napomene); ifile traži(pos); // traži 50. unos Notes Note; //Napomene - gore opisana struktura "zapisa" ifile.read((char*)&Note, sizeof(Notes));
Takve operacije pretraživanja su efikasne ako se datoteka sastoji od zapisa poznate i konstantne veličine. Da biste zamijenili sadržaj proizvoljnog unosa, morate otvoriti izlazni tok u modificiranom modu:
Ofstream ofile("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Napomene); ofile seekp(pos); // traži 50. notu Notes Note50 = ("Jeljcin Boris Nikolajevič", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Notes)); // zamjena
Ako ne navedete oznaku ios::ate (ili ios::app), onda kada otvorite binarnu datoteku Notebook.dat, njen prethodni sadržaj će biti izbrisan!
Konačno, moguće je istovremeno otvoriti datoteku za čitanje/pisanje, koristeći metode koje naslijeđuje fstream streaming klasa od svojih prethodnika. Budući da je klasa fstream izvedena iz istream i ostream (roditelji ifstreama i ofstreama, respektivno), sve prethodno spomenute metode postaju dostupne aplikaciji.
Sljedeći primjer zamjenjuje prvi i treći unos u datoteci Notebook.dat.
#include
Oznake ios::in i ios::out moraju biti specificirane u konstruktoru objekta datoteke kako bi se omogućile istovremene operacije čitanja i pisanja. Kao rezultat izvršavanja ovog koda, prvi i treći zapis binarne datoteke Notebook.dat će biti zamijenjeni.
Postoje dodatni primjeri na ovu temu.