* Работа с файлове от високо ниво
Публикувано на 26 октомври 2008 в раздел С/С++.
Когато създаваме каквато и да е програма обработваща данни обикновено се налага да съхраняваме данните след приключването на програмата. Много често се налага и прочитане на данни от вече съществуващи файлове. В С функциите за достъп до файлове от високо ниво са fopen, fclose, getc, putc, fgetc, fputc, ungetc, fseek, fprintf, sprintf, fscanf, sscanf, remove, fgets и fputs. Всички те се намират в stdio.h.
Преди да започнем описанието на функциите трябва да отбележим, че има два вида достъп до дискови файлове - буфериран и небуфериран. Функциите от високо ниво използват буфериран достъп до файловете. При него се чете или записва символ по символ и програмистът не се занимава със системно зависими особености.
1. fopen: Функция, чрез която се отваря файл и връща резултат указателя на файла. Също така определя допустимите операции при буфериран достъп.
FILE *fp; fp = fopen(char *name, char *mode);
Тук името на файла представлява всеки валиден за операционната система път (зададен като символен низ). Режимът (mode) е един от следните символни низове:
"r" - за четене "w" - за запис. "a" - за добавяне към съществуващ файл "r+" - за четене и запис "w+" - за създаване на файл и запис в негол "a+" - за добавяне към съществуващ файл и промяна в него
Важно: при w и w+ всичката текуща информация във съществуващ файл ще бъде изтрита!
Променливата fp е задължително от тип FILE и трябва да бъде указател. Функцията fopen ще върне указател към файла ако резултатът е успешен или NULL (0) ако не е. Затова често функцията се използва по следния начин:
FILE *fp; fp = fopen("file.txt", "r"); // Тук можем да използваме също if(fp==0)... или if(fp==NULL)... if (!fp) printf("Cannot open file");
2. fclose: Функция, чрез която затваряме файл, отворен чрез fopen. Използува се за освобождаване на всички системни ресурси. По-важно, е че ако има все още незаписане данни, които стоят в буфера - при извикването на fclose те се записват. Затова в никакъв случай не трябва да забравяте отворени файлове! Синтаксисът е следния:
fclose(FILE *fp);
Функцията ще върне резултат 0 при успешно изпълнение и -1 при грешка.
3. getc: Използува се за извеждане на един символ от файл, отворен за четене с fopen. Като резултат от изпълнението функцията връща символа, прочетен от файла. Освен това всяко следващо извикване ще връща следващ символ от файла. Следния пример демонстрира как можем да прочетем един файл и да го отпечатаме на екрана:
FILE *fp; fp = fopen("test.txt", "r"); if (fp){ char c = getc(fp); while (c != EOF){ printf("%c", c); c = getc(fp); } fclose(fp); } else printf("cannot open file");
Константата EOF (стойност -1) се достига когато сме достигнали до край на файла. Имайте предвид, че getc е макрос и може да доведе до нежелани ефекти.
4. putc: Записва символ във файл отворен за запис чрез fopen. Отново както getc е реализиран като макрос. Синтаксисът е следния:
putc(char c, FILE* fp);
Следният пример демонстрира как записваме символен низ във файл (отново припомняме, че съществуващата информация във файла при режим "w" се изтрива):
char *niz = "I want to save this text"; FILE *fp; fp = fopen("test.txt", "w"); if (fp){ while (*niz != '\0'){ putc(*niz, fp); niz++; } fclose(fp); } else printf("cannot open file"); return 0;
5. fgetc/fputc: Две функции напълно аналогични като синтаксис и употреба като getc и putc. Съществената разлика е именно, че са "функции", тоест заемат по-малко памет и са относително по-сигурни. Абсолютно препоръчително е при запис на големи количества данни да се използват именно тези две функции!
6. ungetc: Това е интересна функция, която манипулира буфера. Тя може да се каже, че е обратната на getc - заменя текущия символ във файла с подаден нов. Следният пример демонстрира как когато извеждаме символен низ на екрана всички звездички (*) в него ще бъдат променени в символа '@':
fp = fopen("test.txt", "r"); if (fp){ char c = getc(fp); while (c != EOF){ if (c == '*'){ // Тук все едно "се връщаме назад" // в буфера и заменяме символа с '@' c = ungetc('@',fp); c = getc(fp); } printf("%c", c); c = getc(fp); } fclose(fp); } else printf("cannot open file")
7. fseek: Чрез тази функция се осъществява "преместване" до определена позиция във файла. Използва се, когато данните във файла са структурирани с определена дължина:
fseek(FILE *fp, int position, int mun);
Параметърът position указва с колко байта да се отместим във файла. Параметърът mun може да приема стойности 0 (спрямо началото на файла), 1 (спрямо текущата позиция) и 2 (спрямо края на файла "наобратно"). Следната функция връща (i+1)-вия поред символ от подаден файл:
char readi(FILE *fp, long i){ fseek(fp, i, 0); return (getc(fp)); }
8. Функциите fprintf, sprintf, fscanf и sscanf са форматиран вход/изход за низове и файлове от високо ниво. Те действат аналогично както printf и scanf, но областта им на действие е съсредоточена към низове и файлове. Синтаксис:
sprintf(char *string, "форматиращи_параметри", аргументи); fprintf(FILE *file, "форматиращи_параметри", аргументи); sscanf(char *string, "форматиращи_параметри", аргументи); fscanf(FILE *file, "форматиращи_параметри", аргументи);
9. Функцията remove се използва за изтриване на файл. Той не трябва да бъде отворен. Като входен параметър приема името на файла (или пълният път до него + името) като символен низ. Връща 0 при успех и -1 при грешка.
10. fgets: Чете следващия входен ред (включително и символа за нов ред) от файла fр и го записва в символния масив line;
fgets(char *line, int maxline, FILE *fp)
Четат се най-много maxline-1 символа. Maxline трябва да е по-голяма или равна на размерността на масива line, в който записваме. Последният символ винаги е край на символен низ ('\0'). Функцията връща NULL при край на файл.
11. fputs: Записва символен низ (който може и да не съдържа символ за нов ред) в даден файл:
int fputs(char *line, FILE *fp)
Функцията връща 0 при успех и EOF при грешка.
Задача: Реализирайте функции за четене и запис на информацията в последната задача от темата за структури
Задача: Напишете функция, която приема указател към два файла. Функцията трябва да върне 0 ако те се различават и 1 ако са еднакви.
Задача: Нека в предишната задача се отпечата и първата линия, с която файловете се различават.
Задача: Напишете функция, която по зададени символ и указател към файл да връща броя на срещанията на символа във този файл.
ще дадеш ли по един пример за fprintf и fscanf ?? и 10х за темата , много е полезна :)
Пример - записва числото i във файл:
int i = 5;
fp = fopen("test.txt", "w");
if (fp){
fprintf(fp, "%d", i);
fclose(fp);
}
else printf("cannot open file");
Действа точно както printf и scanf - просто вместо към стандартния вход/изход четат/пишат от файл.
да , схванах идеята на тия функции , 10х :)
В примера за getc си допуснал грешка
char c = getc(fp);
тоя ред "причинява изяждане на първия знак от файла"
Мисля , че е необходимо само да се декларира с и после да и се записва стойност от getc.
Благодаря за забележката. Оправих примера.
Искам също да кажа,че ако някой иска да сложи абсолютен път а не релативен като колега, да знае че C:\NewFile.txt се пише C:\\NewFile.txt .
Ok, всичко си работи, но когато се опитам да обработя файл от няколко килобайта програмата спира. Обработва малко над 400 знака и прекъсва без да дава съобщение за грешка.
Някаква идея, на какво може да се дължи това?