C, PHP, VB, .NET

Дневникът на Филип Петров


* Работа с файлове от високо ниво

Публикувано на 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 ако са еднакви.

Задача: Нека в предишната задача се отпечата и първата линия, с която файловете се различават.

Задача: Напишете функция, която по зададени символ и указател към файл да връща броя на срещанията на символа във този файл.

 



7 коментара


  1. ще дадеш ли по един пример за fprintf и fscanf ?? и 10х за темата , много е полезна :)

  2. Пример - записва числото i във файл:

    int i = 5;
    fp = fopen("test.txt", "w");
    if (fp){
    fprintf(fp, "%d", i);
    fclose(fp);
    }
    else printf("cannot open file");

    Действа точно както printf и scanf - просто вместо към стандартния вход/изход четат/пишат от файл.

  3. В примера за getc си допуснал грешка
    char c = getc(fp);
    тоя ред "причинява изяждане на първия знак от файла"
    Мисля , че е необходимо само да се декларира с и после да и се записва стойност от getc.

  4. Искам също да кажа,че ако някой иска да сложи абсолютен път а не релативен като колега, да знае че C:\NewFile.txt се пише C:\\NewFile.txt .

  5. Ok, всичко си работи, но когато се опитам да обработя файл от няколко килобайта програмата спира. Обработва малко над 400 знака и прекъсва без да дава съобщение за грешка.
    Някаква идея, на какво може да се дължи това?

Добави коментар

Адресът на електронната поща няма да се публикува


*