Windows: c:\directory\file nie uwzględnia wielkość liter
Linux: /directory/file uwzględnia wielkość liter
i jeśli chcemy zapisać w stringu to w linuxie: char *name="/dir/file:'
to w windows: char *name="c:\\dir\\file";
3 sposoby otwarcia strumienia:
read
write
update (read&write)
binarny vs tekstowy
tekstowy w liniach
binarny, sekwencja bajtów
W unix koniec linii to LF (ASCII kod 10) w C \n
w windows CR LF (ASCII 13 10) w C \r\n
polecenie dostępu do pliku:
FILE *fopen(char *filename, char *openmode);
jeśli sukces zwraca wskaźnik typu FILE, jeśli nie zwraca NULL
filename - nazwapliku
openmode - tryb odczytu
r - read plik musi istniec i byc czytalny (nie istnieje błąd)
w - write, plik nie musi istniec (jak istnieje kasuje, jak nie moze stworzyć błąd)
a - append , jeśli istnieje dopisze na końcu
r+ - read and update, plik musi istniec, mozliwy odczyt i zapis
w+ - write and update, plik nie musi istnieć, jeśli istnieje kasuje
dodanie literki b - np: rb, wb, ab...tryb binarny
tryb tekstowy domyślny, ale mozna dopisać t np: rt, wt, at
przykład:
FILE *file; file = fopen("c:\\users\\user\\Desktop\\file.txt","rt"); if(file == NULL) { printf("File cannot be opened"); return 1; }
można skrócić do 1 linijki:
if((file = fopen("c:\\users\\user\\Desktop\\file.txt", "rt")) == NULL) {... }
3 OTWARTE STRUMIENIE
jeśli mamy dyrektywę
#include<stdio.h>
FILE *stdin, *stdout, *stderr;
stdin - standard input, zwykle klawiatura (scanf czyta standardowo z tego strumienia)
stdout - standard output, zwykle ekran, standardowe wyjscie dla programow, printf wyrzuca na ekran
stderr - standard error output - standardowo ustawione na ekran,
można zmienić cel strumieni
FCLOSE
zamyka plik, wymaga tylko wskaźnika do pliku
zwraca 0 na sukces lub EOF (-1) na błąd
int fclose(FILE *stream);
ERRNO
Error number
wymaga errno.h
extern int errno;
operacje na strumieniach które spowodują błąd zapiszą go do tej zmiennej
EACCES - brak dostępu
EBADF - próba operacji na nie otwartym pliku
przykład:
FILE *file = fopen("c:\\file.txt","rt"); if(file == NULL) { switch(errno) { case ENOENT: printf("The file doesn't exist\n"); break; case EMFILE: printf("You've opened too many files\n"); break; default: printf("The error number is %d\n",errno); } }
istnieje automatyczny sposób dotarcia do opisu błędu:
strerror (wymaga string.h)
char *strerror (int errnum);
podajesz numer błędu i dostajesz wskaźnik do tekstu opisującego znaczenie błędu.
FUNKCJE CZYTAJĄCE ZE STRUMIENI
FGETC
fgetc - czyta jeden znak ze strumienia
int fgetc(FILE *stream);
fgetc(stdin);
przykład odczytywania znak po znaku pliku i wyswietlaniu tego na ekran:
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { FILE *inp; int chr; /* check if there is one argument */ if(argc != 2) { printf("usage: show file_name\n"); return 1; } /* check if we are able to open the input file */ if((inp = fopen(argv[1],"rt")) == NULL) { printf("Cannot open the file %s\n", argv[1]); return 2; } /* we will try to read the file char by char and print the chars to screen */ while((chr = fgetc(inp)) != EOF) printf("%c",chr); /* it's time to close the stream */ fclose(inp); return 0; }}
FGETS
czyta string ze streamu
char *fgets(char *str, int maxsize, FILE *stream);
str - wskaźnik gdzie fgets będzie gromadził linie wziętą ze strumienia
maxsize - maksymalna liczna znaków możliwa do przechowania w str
stream - wskaźnik do strumienia (reading or update)
Funkcja czyta linie i zapisuje w buforze, jesli sukces zwraca wartość parametru str i przesuwa punkt czytania w nowe miejsce
NIE do czytania binarnych plików (czytanie ich linia po lini nie ma sensu) oraz gdy w binarnym bedzie \0 odczyta jako koniec wiersza
odmiana tej funkcji to
char* gets(char* str) która czyta ze strandardowego wejscia (stdin-klawiatura) ale nie sprawdza czy to pomieści się w str !!!
przykład odczytujący całe linie:
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { FILE *inp; char line[128]; if(argc != 2) { printf("usage: show2 file_name\n"); return 1; } if((inp = fopen(argv[1],"rt")) == NULL) { printf("Cannot open the file %s\n", argv[1]); return 2; } while((fgets(line,sizeof(line),inp)) != NULL) printf("%s",line); fclose(inp); return 0; }
FREAD
odczytuje bajty ze strumienia
int fread(voif *mem, int size, int count, FILE *stream);
mem - wskaźnik do obszaru gdzie bedzie zapisywał bajty
size - rozmiar w bajtach jaki bedzie zapisywal
count - ilosc porcji zapisu
stream - co bedzie czytal
funkcja zwraca ilosc poprawnie odczytanych porcji, idealna do odczytu plików binarnych, można również czytać tekstowe, ale nie bez uwzględniania podziału na linie
przykład:
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { FILE *inp; unsigned char buffer[1024]; /* 1 kilobyte */ int i, read; if(argc != 2) { printf("usage: show3 file_name\n"); return 1; } if((inp = fopen(argv[1],"rb")) == NULL) { printf("Cannot open the file %s\n", argv[1]); return 2; } do { read = fread(buffer,1,sizeof(buffer),inp); for(i = 0; i < read; i++) printf("%02X",buffer[i]); } while (read > 0); fclose(inp); return 0; }
FSCANF
jeśli w pliku mamy 3 kolejne znaku jako 128 i chcemy je odczytać jak jedną zmienna np typu INT
to tylko FSCANF pozwoli nam tego dokonać
fscanf działa tak jak scanf, tyle że dodajemy dodatkowo, jako pierwszy parametr, wskaźnik do pliku, który chcemy odczytać, np.:
fscanf ( wskaznik_dopliku, "%d", zmienna_int )
Takie wywołanie funkcji spowoduje odczytanie elementu z pliku jako typ int i przypisanie go do zmiennej zmienna_int, albo innego typu (jesli float to 2 parametr "%f" )
Po odczytaniu kolejnych elementów wskaźnik pliku jest odpowiednio przesuwany na miejsce, w którym kończy się dany element.
Najlepiej korzystać z funkcji fscanf, jeśli odczytujemy plik, który zawiera szczególny rodzaj danych - nie tylko tekst, ale np. liczby różnych typów. Można wtedy bezpośrednio zapisać kolejne elementy pliku do odpowiednich zmiennych
przykład sortowania int wyciągniętych z plików tekstowych
#include <stdio.h> #include <errno.h> #include <string.h> int main(int argc, char *argv[]) { int numbers[1000]; int i,aux; int numbersread = 0; int swapped; FILE *inp; if(argc != 2) { printf("usage: intsort input_file\n"); return 1; } if((inp = fopen(argv[1],"rt")) == NULL) { printf("Cannot open %s - %s\n",argv[1],strerror(errno)); return 2; } while(fscanf(inp,"%d",&numbers[numbersread]) == 1) { numbersread++; if(numbersread == 1000) break; } fclose(inp); if(numbersread == 0) { printf("No numbers found in the files %s\n",argv[1]); return 3; } do { swapped = 0; for(i = 0; i < numbersread - 1; i++) if(numbers[i] > numbers[i + 1]) { swapped = 1; aux = numbers[i]; numbers[i] = numbers[i + 1]; numbers[i + 1] = aux; } } while(swapped); printf("The sorted values: "); for(i = 0; i < numbersread; i++) printf("%d ",numbers[i]); printf("\n"); return 0; }
ZAPIS
ZAPISYWANIE do pliku tekstowego.
fprintf - jak print ale do pliku
fprintf( wskaznik_dopliku , "%d ", zmienna typu _int )
fputc - zapisuje pojedynczy znak przekazany jako int
int fputc ( int znak , FIL E *wskaznik_dopliku)
fputs - zapisanie łańcucha znaków przekazanego jako parametr
fwrite - zapisanie do pliku danych z tablicy, plik binarny
fwrite(void *ptr, size_t size, size_t nitems, FILE *stream);
Przykład FPUTC
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { FILE *inp, *out; int chr; /* check if we've got exactly two arguments */ if(argc != 3) { printf("usage: copyc source_file target_file\n"); return 1; } /* check if we are able to open the source file */ if((inp = fopen(argv[1],"rb") )== NULL) { printf("Cannot open %s\n", argv[1]); return 2; } /* check if we are able to open the target file */ if((out = fopen(argv[2],"wb")) == NULL) { printf("Cannot create %s\n", argv[2]); fclose(inp); return 3; } /* we are going to read char by char until we reach EOF */ while((chr = fgetc(inp)) != EOF) if(fputc(chr, out) == EOF) break; fclose(inp); fclose(out); return 0; }
Przykład FPUTS
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { FILE *inp, *out; char line[128]; if(argc != 3) { printf("usage: copys source_file target_file\n"); return 1; } if((inp = fopen(argv[1],"rt")) == NULL) { printf("Cannot open %s\n", argv[1]); return 2; } if((out = fopen(argv[2],"wt")) == NULL) { printf("Cannot create %s\n", argv[2]); fclose(inp); return 3; } while((fgets(line,sizeof(line),inp)) != NULL) if(fputs(line,out) == EOF) break; fclose(inp); fclose(out); return 0; }
Przykład FWRITE
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { FILE *inp, *out; char buffer[16384]; /* 16 kilobytes */ int read, written; if(argc != 3) { printf("usage: copyw source_file target_file\n"); return 1; } if((inp = fopen(argv[1],"rb")) == NULL) { printf("Cannot open %s\n", argv[1]); return 2; } if((out = fopen(argv[2],"wb")) == NULL) { printf("Cannot create %s\n", argv[2]); fclose(inp); return 3; } do { read = fread(buffer,1,sizeof(buffer),inp); if(read) written = fwrite(buffer,1,read,out); } while (read && written); fclose(inp); fclose(out); return 0; }
Przykład FPRINTF
#include <stdio.h> #include <errno.h> #include <string.h> int main(int argc, char *argv[]) { int numbers[1000]; int i,aux; int numbersread = 0; int swapped; FILE *inp, *out; if(argc != 3) { fprintf(stderr,"usage: intsort2 source_file target_file\n"); return 1; } if((inp = fopen(argv[1],"rt")) == NULL) { fprintf(stderr,"Cannot open %s: %s\n",argv[1],strerror(errno)); return 2; } if((out = fopen(argv[2],"wt")) == NULL) { fprintf(stderr,"Cannot create %s: %s\n",argv[2],strerror(errno)); fclose(inp); return 3; } while(fscanf(inp,"%d",&numbers[numbersread]) == 1) { numbersread++; if(numbersread == 1000) break; } fclose(inp); if(numbersread == 0) { printf("No numbers found in the file %s\n",argv[1]); return 3; } do { swapped = 0; for(i = 0; i < numbersread - 1; i++) if(numbers[i] > numbers[i + 1]) { swapped = 1; aux = numbers[i]; numbers[i] = numbers[i + 1]; numbers[i + 1] = aux; } } while(swapped); for(i = 0; i < numbersread; i++) fprintf(out,"%d\n",numbers[i]); printf("\n"); fclose(out); return 0; }
FTELL
pokazuje bieżącą pozycje w strumieniu
long ftell(FILE *stream);
zwraca dystans w bajtach policzony od początku pliku
jeśli bła zwraca EOF (-1)
nie wpływa na pozycję
FSEEK
ustawia bieżącą pozycję
int fseek (FILE * stream, long offser, int whence);
offset - docelowa pozycja
whence - skąd liczona
SEEK_SET - beginning
SEK_CUR - current
SEEK_END - end
jeśli błąd EOF(-1), oczywiściew wpływa na bieżącą pozycję
FILE *F;
fseek(F, 100, SEEK_SET);
fseek(F, -1, SEEK_CUR);
REWIND
z czasów taśm
nic nie zwraca, nie ustawia ERRNO
void rewind(FILE *stream)
równoznaczne z
fseek(stream, 0, SEEK_SET); // czyli ustawia na początek
EOF i funkcja FEOF
end of file - pojawia się gdy nic do czytania
int feof(FILE *stream);
zwraca 0 gdy plik nie jest EOF albo zwraca coś innego jak JEST
więc można sprawdzić czy jest:
while(!feof (input))
{
fgets (line, sizeof(line), input));
fputs (line, output);
}
ZADANIA
Zad1
#include <stdio.h>
int main(void) {
FILE f;
f = fopen("file","wb");
printf("%d",f != NULL);
fclose(f);
return 0;
}
Wynik błąd kompilacji bo brak * w FILE f
Zad2
#include <stdio.h>
int main(void) {
FILE *f;
f = fopen("file","wb");
printf("%d",f != NULL);
fclose(f);
return 0;
}
Wynik 1, bo wszystko ok
Zad3
#include <stdio.h>
int main(void) {
int i;
i = fprintf(stdin,"Hello!");
printf("%d",i == EOF);
return 0;
}
Wynik 0 , przeanalizować
Zad4
#include <stdio.h>
int main(void) {
int i;
i = fprintf(stderr,"Hello!");
printf("%d",i == EOF);
return 0;
}
Wynik 0, ale dodatkowo na wyjsciu blędów, czyli ekranie wyswietli hello, wiec bedzie Hello!0
Zad5
#include <stdio.h>
int main(void) {
FILE *f;
int i = fprintf(f,"Hello!");
printf("%d",i == EOF);
return 0;
}
Wynik błąd wykonania, bo nie ma otwarcia pliku
Zad6
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
int i = fprintf(f,"Hello!");
printf("%d",i != EOF);
return 0;
}
Wynik 1 bo OK
Zad7
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
int i = fputs(f,"Hello!");
printf("%d",i != EOF);
fclose(f);
return 0;
}
Wynik błąd, bo fputs...przeanalizować !!
Zad8
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
int i = fputs("Hello!",f);
printf("%d",i != EOF);
return 0;
}
Wynik 1, fputs poprawnie :-)
Zad9
#include <stdio.h>
int main(void) {
char s[20];
FILE *f = fopen("file","w");
int i = fputs("12A",f);
fclose(f);
f = fopen("file","r");
fgets(s,2,f);
puts(s);
fclose(f);
return 0;
}
Wynik 1 , przeanalizować czemu nie 2 znaki
Zad10
#include <stdio.h>
int main(void) {
char s[20];
FILE *f = fopen("file","w");
int i = fputs("12A",f);
fclose(f);
f = fopen("file","r");
fgets(s,20,f);
puts(s);
fclose(f);
return 0;
}
Wynik 12A
Zad11
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
int i;
fputs("12A",f);
fclose(f);
f = fopen("file","r");
fseek(f,0,SEEK_END);
i = ftell(f);
fclose(f);
printf("%d",i);
return 0;
}
Wynik: 3, bo jest na koncu a mamy 3 znaki
Zad12
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
int i;
fputs("12A",f);
fclose(f);
f = fopen("file","r");
fseek(f);
i = ftell(f,0,SEEK_END);
fclose(f);
printf("%d",i);
return 0;
}
Wynik błąd, bo fseek potrzebuje wiecej argumentow
Zad13
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
int i;
fputs("12A",f);
fclose(f);
f = fopen("file","r");
fscanf(f,"%d",&i);
fclose(f);
printf("%d",i);
return 0;
}
Wynik 12, bo odczytuje liczbę int za pomocą fscanf
Zad 14
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
char c;
fputs("12A",f);
fclose(f);
f = fopen("file","r");
fscanf(f,"%c",&c);
fclose(f);
printf("%c",c);
return 0;
}
wynik 1, zmyłka, bo nie A jest pierwszym char, ale 1 też nim jest!
Zad15
#include <stdio.h>
int main(void) {
FILE *f = fopen("file","w");
float f;
fputs("12A",f);
fclose(f);
f = fopen("file","r");
fscanf(f,"%f",&f);
fclose(f);
printf("%f",f);
return 0;
}
Wynik błąd, ale zmyłka bo float f pokrywa się z FILE *f, gdyby float był inny wynik 12.0000