Obsługa plików
proceduralna - biblioteka stdio (C)
obiek
e t
k owa
w - bibliotek
e a
k fstre
r a
e m (C+
C +)
Obsługa we/wy na poziomie strumieni
Strumienie są reprezentowane przez zmienne typu FILE i są kojarzone z plikami dyskowymi i urządzeniami.
FILE * strm
- deklaracja strumienia;
FILE *fopen(const char * nazwa_pliku, const char * tryb_otwarcia) - otwarcie pliku, zwr
w aca w
a
w rtoś
o ć
ś NU
N L
U L
L jeśl
ś i ope
racja ot
wa
w rcia pl
iku s
ku i
s ę ni
e pow
i
pow odła,
argumentami są nazwa pliku (łańcuch) oraz tryb otwarcia pliku (łańcuch); int fclose( strm) - zamknięcie strumienia o nazwie strm, zwraca 0 jeśli operacja została zakończona powodzeniem i wartość EOF jeśli wystąpił błąd.
int fcloseall(void) – zamknięcie wszystkich strumienie poza standardowymi, zwraca wartość równą liczbie zamkniętych strumieni jeśli operacja została zakończona powodzeniem lub wartość EOF jeśli wystąpił błąd.
Obsługa we/wy na poziomie strumieni
Strumienie standardowe (zawsze otwarte):
- stdin - strumień wejściowy (konsola),
- stdout - strumień wyjściowy (konsola),
- st
s derr – st
s rumi
um eń
ń komuni
kom
katów
ów bł
ędów,
dów
- stdaux – strumień pomocniczy,
- stdprn – strumień drukarki.
Obsługa we/wy na poziomie strumieni
Rodzaje i tryby otwarcia plików
b - plik binarny , t - plik tekstowy
r
- otwarcie w trybie tylko do odczytu,
w
- otwarcie w trybie tylko do zapisu, jeśli plik nie istniał, to zostanie utwor
w zony,
ony a
j
eśl
ś i i
st
s niał, t
o z
o ost
os anie na
dpisa
s ny,
ny
a
- otwarcie w trybie dopisywania (na końcu), jeśli plik nie istniał to zostanie utworzony,
r+
– otwarcie w trybie do modyfikacji (odczyt i zapis), wskaźnik na początku, w+
– otwarcie w trybie do modyfikacji (odczyt i zapis), jeśli plik nie istniał, to zostanie utworzony, a jeśli plik istniał zostanie nadpisany, a+
– otwarcie w trybie do modyfikacji (odczyt i zapis), ustawienie wskaźnika na końcu pliku, jeśli plik nie istniał zostanie utworzony.
przykłady trybów otwarcia:
”wb” – otwarcie pliku binarnego w trybie do zapisu,
”a+b” – otwarcie pliku binarnego w trybie do aktualizacji z możliwością odczytu i zapisu, pozycja wskaźnika na końcu pliku.
Obsługa we/wy na poziomie strumieni
Przykład. Otwarcie i zamknięcie pliku
#include <stdio.h>
main()
{ char *nazwa_pliku=”d:\\wsti\\wyklady\\programy\\plik_pom”; FILE *strm;
int k;
strm = fopen(nazwa_pliku,”rb”);
if (strm==NULL)
fputs(”blad otwarcia pliku”, stdout);
// zamiast printf((”blad otwarcia pliku”);
else
{
fputs(”plik został otwarty w trybie do odczytu”, stdout); k=fclose(strm);
if (k==EOF)
fputs(”blad zamknięcia strumienia”, stdout);
else
fputs(”strumień zamknięto pomyślnie”, stdout);
}}
}
przykład
Obsługa we/wy na poziomie strumieni
Podstawowe funkcje we/wy
int fgetc(FILE * strm) - odczytuje znak ze strumienia strm, zwraca kod znaku lub wartość EOF gdy wystąpił błąd lub koniec pliku, int fputc(int c, FILE * strm) - zapisuje znak o kodzie c do strumienia strm, zwraca kod z
kod naku l
ku ub E
ub OF
O
F gdy w
y
w st
s ąpił bł
ąd,
char *fgets( char * str, int n, FILE * strm) - odczytuje łańcuch n- 1 znaków ze strumiena strm, i umieszcza je pod adresem str (w tablicy),umieszcza znak końca wiersza oraz znak końca łańcucha (’\0’), zwraca str lub adres pusty (NULL) jeśli koniec zbioru lub błąd,
int fputs(const char * str, FILE * strm) - zapisuje łańcuch znaków wskazywany przez str do strumienia strm, nie wysyła znaku końca łańcucha, w przypadku niepowodzenia zwraca wartość EOF.
C/C++ - obsługa plików - stdio.h
Przykład. Kopiowanie pliku tekstowego
#include <conio.h>
#include <stdio.h>
int main(void)
{
FILE *in, *out;
//deklaracja strumieni
char ch;
in = fopen("d:\\appl.dos\\TC\\programy\\for.cpp", "rt"); out = fopen("d:\\appl.dos\\TC\\programy\\for1.cpp", "wt"); while (! feof(in)){
// feof()== 1 - kiedy koniec pliku
ch=fgetc(in);
putch(ch);//fputc(ch,stdout)
fputc(ch,out);
}
fclose(in);
fclose(out);
przykład
getch();
return 0;
}
C/C++ - obsługa plików - stdio.h
Przykład. Zastosowanie funkcji fputs() i fgets()
#include <conio.h>
#include <stdio.h>
int main(void)
{ char pom[30],*tabstr0[]={"123456","234567","345678"}; FILE *strm;
strm = fopen("d:\\wsti\\wyklady\\programy\\fputs_fgets", "wt"); for(int i=0;i<3;i++) fputs(tabstr0[i],strm);
fclose(strm);
strm = fopen("d:\\wsti\\wyklady\\programy\\fputs_fgets", "rt"); fgets(pom,19,strm);
printf("%s\n",pom);
fclose(strm);
getch();
return 0;
}
przykład
Obsługa we/wy na poziomie strumieni
Podstawowe funkcje we/wy – odczyt, zapis liczby typu int
int getw(FILE * strm) - odczytuje liczbę typu int ze strumenia strm, zwraca wartość EOF kiedy błąd lub koniec pliku. Funkcji nie należy używać w trybie tekstowym, a do określania końca pliku należy używać funkcji feof() gdyż EOF może być „zwykłą” wartością.
int putw(int w, FILE * strm) - zapisuje liczbę w typu int do strumienia strm, zwraca liczbę w lub EOF kiedy wystąpił błąd,
Obydwu funkcji brak w Dev C++.
Obsługa we/wy na poziomie strumieni
Podstawowe funkcje we/wy – odczyt , zapis blokowy
size_t fread(void * bufor, size_t rozmiar, size_t n, FILE * strm) - odczytuje ze strumienia strm n bloków wielkości rozmiar każdy i umieszcza je pod adresem bufor. Funkcja zwraca liczbę odczytanych bloków.
si
s ze_t fwr
w ite(const
ons void * buf
*
or,
or s
i
s ze_t roz
r m
oz i
m ar,
ar si
s ze_t n,
n F
I
F LE *
s
* t
s rm
r )
m -
zapisuj
s e
do strumienia strm n bloków wielkości rozmiar każdy, dane pobierane są spod adresu bufor. Funkcja zwraca liczbę wysłanych bloków.
Przykład. Blokowy zapis do pliku i odczyt wektora liczb.
#include "losowanie.c"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
przykład
#include <conio.h>
int main(void)
{
const int N=20;
FILE *plik;
int wek[N],wek1[N],x;
randomize;
for(int i=0;i<N;i++) wek[i]=random(N);
plik = fopen("d:\\wsti\\wyklady\\programy\\fread_fwrite","wb"); fwrite(wek,sizeof(int),N,plik);
fclose(plik);
plik = fopen("d:\\wsti\\wyklady\\programy\\fread_fwrite",„rb"); fread(wek1,sizeof(int),N,plik);
fclose(plik);
for(int i=0;i<N;i++) printf("%d ",wek[i]);
printf("\n");
for(int i=0;i<N;i++) printf("%d ",wek1[i]);
getch();
return 0;
}
Obsługa we/wy na poziomie strumieni
Formatowane we/wy - funkcje fprintf(), fscanf()
(należą do jednej rodziny z funkcjami printf() i scanf()) int fprintf(FILE * strm, const char * lan_formatu, typ parametr1,typ parametr2, ...); zapis
s do
s
do t
s rumi
um enia s
t
s rm
r
zgodnie z
ł
ańc
ń uchem
m f
orma
m tującym
m l
an_form
or at
m u z
uwzględnieniem wartości parametrów: parametr1, parametr2, ... ; funkcja nie zapisuje znaku końca łańcucha.
int fscanf (FILE * strm, const char * lan_formatu, typ * arg1,typ * arg2, ...); odczyt ze strumienia strm zgodnie z łańcuchem formatującym lan_formatu i umieszczenie danych w zmiennych: arg1, arg2, ...
Specyfikatory formatu funkcji fprintf() :
%c
- znak;
%s
- łańcuch znaków;
%d
- liczba całkowita ze znakiem w systemie dziesiętnym;
%u
- liczba całkowita bez znaku w systemie dziesiętnym;
%f
- liczba zmiennoprzecinkowa z kropką;
%Lf
- liczba z
mi
m ennoprzecinkowa
nkow t
ypu doubl
pu
e;
%e
- liczba zmiennoprzecinkowa w zapisie wykładniczym;
%Le
- liczba zmiennoprzecinkowa w zapisie wykładniczym typu long double;
%g
- krótszy z formatów %f i %e;
%o
- liczba w systemie ósemkowym;
%x
- liczba w systemie szesnastkowym;
%%
- znak %.
Specyfikatory formatu funkcji fscanf():
%c
- znak;
%s
- łańcuch znaków;
%d
- liczba całkowita ze znakiem w systemie dziesiętnym;
%u
- liczba c
ałkowi
kow ta be
z z
naku w
ku
w sy
s st
s emi
m e dz
iesi
s ętnym;
m
%f
- liczba zmiennoprzecinkowa z kropką;
%Lf
- liczba zmiennoprzecinkowa typu double;
Przykład. Formatowane we/wy. Zapis do pliku i odczyt wektora liczb.
#include "losowanie.c"
przykład
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
int main(void)
{
const int N=20;
FILE *plik;
int wek[N],wek1[N],x;
randomize;
for(int i=0;i<N;i++) wek[i]=random(N);
plik = fopen("d:\\appl.dos\\TC\\programy\\dane","wb"); for(int i=0;i<N;i++) fprintf(plik,"%d\n",wek[i]); fclose(plik);
plik= fopen("d:\\appl.dos\\TC\\programy\\dane","rb"); for(int i=0;i<N;i++){
fscanf(plik,"%d",&x);
wek1[i]=x;
}
fclose(plik);
for(int i=0;i<N;i++) printf("%d ",wek1[i]);
getch();
return 0;
}
C/C++ - obsługa plików - stdio.h
Przykład - kartoteka, zapis do pliku i odczyt
kartoteka_formatowane_wewy
kartoteka_blokowe_wewy
Wykorzystywana struktura
struct adr{
KARTOTEKA
char ulica[15];
unsigned dom;
unsigned lokal;
unsigned kod_pocztowy;
};
struct osoba{
char nazwisko[20];
char imie[15];
struct adr adres;
int wskaznik_zajetosci;
};
Odczyt danych za pomocą funkcji fscanf() void kart_odczyt_z_pliku(osoba kart[])
{ FILE *plik;
KARTOTEKA
plik = fopen(".\\kartoteka", "rb");
if (plik==NULL)
cout<<"\nkartoteka nie istnieje, wpisz dane"; else
{ int i=0;
while (!feof(plik)){
fscanf(plik,"%s",kart[i].nazwisko);
fscanf(plik,"%s",kart[i].imie);
fscanf(plik,"%s",kart[i].adres.ulica);
fscanf(plik,"%u",&kart[i].adres.dom);
fscanf(plik,"%u",&kart[i].adres.lokal);
kart[i].wskaznik_zajetosci=1; i++; }
fclose(plik);
}}
Zapis danych za pomocą funkcji fprintf() void kart_zapis_do_pliku(osoba kart[])
{
KARTOTEKA
FILE *plik;
plik = fopen(".\\kartoteka", "wb");
int i=0;
while (kart[i].wskaznik_zajetosci!=-1){
fprintf(plik,"%s%c",kart[i].nazwisko,'\n');
fprintf(plik,"%s%c",kart[i].imie);
fprintf(plik,"%s%c",kart[i].adres.ulica,'\n');
fprintf(plik,"%u%c",kart[i].adres.dom,'\n');
fprintf(plik,"%u",kart[i].adres.lokal);
i++;
}
fclose(plik);
}
Odczyt danych za pomocą funkcji odczytu blokowego fread() void kart_odczyt_z_pliku(osoba kart[],int n)
{ FILE *plik;
plik = fopen(".\\kartoteka_blok", "rb"); if (plik==NULL)
cout<<"\nkartoteka nie istnieje, wpisz dane"; else
{
fread(kart,sizeof(osoba),n,plik);
fclose(plik);
}}
Zapis danych za pomocą funkcji zapisu blokowego fwrite() void kart_zapis_do_pliku(osoba kart[],int n)
{
FILE *plik;
plik = fopen(".\\kartoteka_blok", "wb"); fwrite(kart,sizeof(osoba),n,plik);
fclose(plik);
}
Obsługa we/wy na poziomie strumieni
Dostęp bezpośredni do elementów strumienia – sterowanie wskaźnikiem pozycji strumienia.
Podstawowe funkcje realizujące operacje na plikach, także funkcje forma
m towa
ow nego w
go e
w /wy
w pr
zetwa
w rzają pl
iki w
w spos
s
ób
pos
se
s kwe
kw ncyjny.
ny
. K
a
K żdy odc
zyt
lub zapis powoduje jednostkową zmianę położenia wskaźnika pozycji.
Istnieją jednak funkcje pozwalające na sterowanie pozycją wskaźnika, co umożliwia bezpośredni dostęp do danych.
Obsługa we/wy na poziomie strumieni
Dostęp bezpośredni do elementów strumienia – sterowanie wskaźnikiem pozycji strumienia.
int fseek(FILE * strm, long l_bajtow, int odpozycji); - przesuwa wskaźnik pozycji pliku na pozycję równą odpozycji+ l_bajtów; parametr odpozycji może przyjmować wartości 0,1 lub 2:
0 –
0 początek pl
k iku
1 – pozycja bieżąca
2 – koniec pliku
l_bajtow można nazwać offsetem, może on przyjmować wartości zarówno dodatnie jak i ujemne.
void rewind(FILE * strm); - ustawia wskaźnik pozycji pliku na jego początek.
Obsługa we/wy na poziomie strumieni
Dostęp bezpośredni do elementów strumienia – sterowanie wskaźnikiem pozycji strumienia.
int fgetpos(FILE * strm, fpos_t * pozycja); - zapisuje wskaźnik pozycji pliku pod adresem pozycja, kod poprawnego wykonania operacji - 0; int fsetpos(FILE * strm, const fpos_t * pozycja); - ustawia wskaźnik pozycji pliku zgodnie z wartością parametru pozycja, kod
poprawnego wykonania operacji - 0;
long ftell(FILE * strm); - zwraca wskaźnik pozycji w pliku związanym ze strumieniem strm mierzony liczbą bajtów w stosunku do początku pliku
Obsługa we/wy na poziomie strumieni
Funkcje pozostałe
int fflush(FILE * strm); - wysłanie zawartości bufora związanego ze strumieniem wyjściowym do pliku (opróżnienie bufora);
int r
emove
m
(const
ons char *
nazw
naz a
w );
- usuni
us
ęcie pl
iku o
ku podanej na
zwi
w e;
int rename(const char * stara _ nazwa, const char *nowa_ nazwa); - zmiana nazwy pliku;
Przykład. Obsługa pliku w trybie jednoczesnego zapisu i odczytu, sterowanie położeniem wskaźnika (funkcja fseek()).
#include "losowanie.c"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
int main(void)
{ const int N=5;
FILE *plik;
int wek[N],x;
randomize;
for(int i=0;i<N;i++) wek[i]=random(N);
plik = fopen("d:\\wsti\\wyklady\\programy\\fseek", "w+b"); for(int i=0;i<N;i++){
fprintf(plik,"%d",wek[i]);
fseek(plik,-1L,1); // korekcja wskaźnika pozycji o 1 wstecz fscanf(plik,"%d",&x);
printf("%d",x);}
fclose(plik);
printf("\n");
for(int i=0;i<N;i++) printf("%d ",wek[i]);
getch();
return 0;
przykład
}
C++- obsługa plików - fstream.h
Obsługa plików z wykorzystaniem strumieni
W języku C++ plik otwiera się przez skojarzenie go ze strumieniem. Istnieją trzy typy strumieni definiowane przez 3 klasy: wejściowy (ifstream), wyjściowy (ofstream) oraz wejściowo-wyjściowy (fstream)
Aby wykonywać operacje na plikach należy zadeklarować zmienną (obiekt) danej klasy, np. :
fstream plik;
W
W da
lsz
s ej c
zęśc
ś i om
ów
om
i
ów ona zost
os anie obs
ł
obs uga pl
ików
ków z
w
y
w korzyst
s aniem
e
m kl
asy
s
fstream.
Wybrane funkcje (metody) klasy fstream:
open() – otwarcie pliku;
close() – zamknięcie pliku;
get() – odczyt z pliku ;
put() – zapis do pliku;
write() – zapis blokowy do pliku;
read() – odczyt blokowy z pliku;
tellg() – odczyt położenia wskaźnika pliku;
seekg() – ustawienie wskaźnika pliku.
do obsługi plików tekstowych można używać poleceń in>>, out<<
C++- obsługa plików - fstream.h
Obsługa plików z wykorzystaniem strumieni
Otwarcie pliku, prototyp:
open(const char * nazwa_pliku, int tryb, int dostep); - otwiera plik nazwa_pliku w trybie określonym przez tryb, a dostęp określa atrybut pliku.
wybrane tryby :
ios::binary - otwarcie w trybie binarnym
ios:
os :in
- otwa
w rcie w
w trybie w
e
w jśc
ś ia (
czytanie)
ios::out
- otwarcie w trybie wyjścia (zapis)
ios::noncreate – nie tworzy pliku w razie jego nieistnienia ios::nonreplace – nie otworzy pliku istniejącego
ios::trunc – nadpisuje poprzednią zawartość
poszczególne tryby można łączyć operatorem sumy bitowej: |
Parametr dostęp może przyjmować wartości: 0 (plik zwykły), 1 (tylko do odczytu), 2 (ukryty), 4 (systemowy), 8 (archiwalny). Parametr jest opcjonalny, a wartością domyślną jest 0) .
close(void); - zamknięcie pliku
C++ - obsługa plików - fstream.h
Obsługa plików z wykorzystaniem strumieni
Zapis, prototyp:
put(char ch); - zapisuje znak (bajt) do pliku.
Odczyt, prototyp:
get(char &
ch); -
odczytuje z
nak z
k pl
iku do
ku
z
do mi
m ennej c
h.
Zapis blokowy, prototyp:
write(const unsigned char * bufor, int size); - zapisuje size bajtów do strumienia z bufora bufor.
Odczyt blokowy, prototyp:
read(unsigned char * bufor, int size); - odczytuje size bajtów ze strumienia i zapisuje w buforze bufor.
C++ - obsługa plików - fstream.h
Obsługa plików z wykorzystaniem strumieni
Ustawianie wskaźnika pliku, prototyp:
seekg(long offset, int origin); - przesuwa wskaźnik pliku o offset bajtów w stosunku do origin.
parametr origin może przyjmować jedną z wartości : ios::beg - początek pliku
ios:
os :cur - położenie bi
eżące
ios::end - koniec pliku
int tellg(void); - odczyt pozycji znacznika pliku w stosunku do początku
Przykład. Blokowy zapis do pliku w trybie tekstowym
#include <conio.h>
#include <fstream>
using namespace std;
int main(void)
{
fstream plik;
char tekst[]="tra la la la";
plik.open(".\\test1",ios::out);
plik.write(tekst,strlen(tekst));
plik.close();
getch();
return 0;
przykład
}
Przykład. Blokowy odczyt z pliku w trybie tekstowym
#include <conio.h>
#include <iostream>
#include <fstream>
// dodanie biblioteki fstream
using namespace std;
int main(void)
{ fstream plik;
char *tekst;
plik.open(".\\test1",ios::in); //otwarcie pliku
//do odczytu
plik.seekg(0,ios::end);//ust. znacznika na koniec pliku int l=plik.tellg(); //odczyt pozycji znacznika
plik.seekg(0,ios::beg);// ustawienie znacznika na początek plik.read(tekst,l);//odczyt l bajtów do tablicy tekst plik.close();
getch();
przykład
return 0;
}}
Przykład. Blokowy zapis do pliku w trybie binarnym
#include <conio.h>
#include <fstream>
// dodanie biblioteki fstream
using namespace std;
int main(void)
{ const int N=50;
fstream plik; //utworzenie zmiennej klasy fstream char dane[N]="qwerty";
// otwarcie pliku w trybie do zapisu binarnego
// jeśli plik istniał to zostanie nadpisany
plik.open(".\\dane1",ios::out|ios::binary);
plik.write(dane,sizeof(dane)); // zapis
plik.close(); //zamknięcie pliku
getch();
return 0;
przykład
}
Przykład. Blokowy odczyt z pliku w trybie binarnym
#include <conio.h>
#include <iostream>
#include <fstream>
// dodanie biblioteki fstream
using namespace std;
int main(void)
{ fstream plik;
char *tekst;
plik.open(".\\dane1",ios::in| ios::binary); //otwarcie pliku
//do odczytu
plik.seekg(0,ios::end);//ust. znacznika na koniec pliku int l=plik.tellg(); //odczyt pozycji znacznika
plik.seekg(0,ios::beg);// ustawienie znacznika na początek plik.read(tekst,l);//odczyt l bajtów do tablicy tekst plik.close();
getch();
przykład
return 0;
}}