Відкриття файлу

Функція fopen() відкриває потік та зв’язує його з файлом, а після виконання повертає вказівник файлу. Якщо під час відкриття файлу виникла помилка тоді функція fopen() поверне вказівник на NULL.

Синтаксис функції:

*fopen(const char *ім_я_файлу, const char *режим)

ім_я_файлу – вказівник на символьний рядок, що включає повну назву (повний шлях та ім’я).

режим – вказівник на символьний рядок, що визначає режим доступу до файлу.

Табл. Допустимі значення параметру режим.

Параметр Значення
r Відкриття текстового файлу тільки для зчитування.
w Створення й відкриття текстового файлу для додавання. Якщо файл з таким ім’ям існує, тоді він буде замінений новим.
a Відкриття текстового файлу для додавання запису в кінець файлу, якщо він не існує то буде створений.
r+ Відкриття текстового файлу для зчитування та додавання.
w+ Створення й відкриття текстового файлу для додавання та зчитування. Якщо файл з таким ім’ям існує, тоді він буде замінений новим.
a+ Відкриття текстового файлу для додавання та зчитування запису в кінці файлу, якщо він не існує то буде створений.
rb Відкриття бінарного файлу тільки для зчитування.
wb Створення й відкриття бінарного файлу для додавання. Якщо файл з таким ім’ям існує, тоді він буде замінений новим.
ab Відкриття бінарного файлу для додавання запису в кінець файлу, якщо він не існує то буде створений.
r+b, rb+ Відкриття бінарного файлу для зчитування та додавання.
w+b, wb+ Створення й відкриття бінарного файлу для додавання та зчитування. Якщо файл з таким ім’ям існує, тоді він буде замінений новим.
a+b, ab+ Відкриття бінарного файлу для додавання та зчитування запису в кінці файлу, якщо він не існує то буде створений.

Приклад: Вводимо з клавіатури символьний рядок та записуємо його у файл по одному символу.

#include <string.h> #include <stdio.h> #include <iostream> using namespace std;  
int main() { FILE *f; char sf[40]; char str[100];   // оголошуємо файлову змінну // змінна для повного імені файлу
printf("Введіть ім’я файлу: "); gets(sf); f=fopen(sf, "w");   //відкриття файлу для запису
if(f!= NULL) { printf("Введіть символьний рядок: "); gets(str); for(int i=0;i < strlen(str);i++) putc(str[i],f); } else printf("Виникла помилка \n"); // якщо файловий вказівник не вказує на порожність, тоді виконуємо дії
fclose(f); return 0; } // закриваємо файл

Приклад: Зчитування символів з текстового файлу та виведення їх на екран.

#include <string.h> #include <stdio.h> #include <iostream> using namespace std; int main() {  
FILE *f; char sf[40]; char cs; // оголошуємо файлову змінну // змінна для повного імені файлу
printf("Введіть ім’я файлу: "); gets(sf); f=fopen(sf, "r");   //відкриття потоку роботи з файлом для зчитування
if(f!= NULL) { // якщо файловий вказівник не вказує на порожність, тоді виконуємо дії
do {  
cs=getc(f); //зчитування одного символу
cout<<cs; //виведення символу на екран
} while (cs!=EOF); // зчитуємо поки не кінець файлу, тобто коли символ буде вказувати на кінець файлу, зчитування припиняться
} else printf("Виникла помилка \n");  
fclose(f); // закриваємо потік роботи з файлом
return 0; }  

Конструкція зчитування наведена в останньому прикладі може бути використана тільки для роботи з текстовим потоком, тому що при зчитування бінарного потоку при зчитуванні певного елементу в бінарному вигляді може призвести до прийняття зчитаного символу у вигляді EOF. Виходячи з вище сказаного доцільно використовувати функцію feof().

Підхід зчитування по одному елементу з текстового файлу Підхід зчитування по одному елементу з текстового та бінарного файлу
do { while(!feof(f)) {
cs=getc(f); cs=getc(f);
cout<<cs; cout<<cs;
} while (cs!=EOF); }

Приклад запису символьних рядків у текстовий файл, після чого відбувається зчитування файлу по рядкам.

#include <string.h> #include <stdio.h> #include <iostream> using namespace std; int main() {  
FILE *f; char sf[40]; char str[80]; // оголошуємо файлову змінну // змінна для повного імені файлу // змінна для символьного рядку
printf("Введіть ім’я файлу: "); gets(sf); f=fopen(sf, " w+");   //відкриття потоку роботи з файлом для запису та зчитування
if(f!= NULL) { // якщо файловий вказівник не вказує на порожність, тоді виконуємо дії
// запис символьних рядків у файл
do {  
printf("Введіть рядок: ");  
gets(str); //зчитує символьний рядок
strcat(str,"\n"); //додаємо ознаку закінчення рядку
fputs(str,f); //запис символьного рядку в файл
if (ferror(f)) printf("Виникла помилка запису!"); // якщо виникне помилка тоді ferror(f) буде дорівнювати true
} while(*str!='\n'); // введення призупиниться коли буде введено порожній рядок
// курсор знаходиться в кінці файлу, тому необхідно перевести його на початок
rewind(f); //переводимо курсор на початок файлу
// зчитування символьних рядків та запис їх у файл
while (!feof(f)) { fgets(str, 79, f); //зчитування буде відбуватися доки не дійдемо до кінця файлу // fgets(str, 79, f) – зчитує у змінну str символьний рядок до кінця рядка або довжиною 78 з файлу, що пов’язаний з файловим вказівником f
if (ferror(f)) printf("Виникла помилка зчитування!"); // якщо виникне помилка тоді ferror(f) буде дорівнювати true
printf(str); } //виводимо на екран
} else printf("Виникла помилка \n");  
fclose(f); // закриваємо потік роботи з файлом
return 0; }  

Використання функцій fread() та fwrite()

Для зчитування та запису даних, розмір типу яких перевищує 1 байт, файлова система мови С містить дві функції: fread() та fwrite(). Вони використовуються коли файл був відкрито в бінарному (двійковому) режимі. Ці функції дозволяють зчитувати та записувати блоки даних будь-якого типу. Їх прототипи мають наступний вигляд:

size_t fread (void *буфер, size_t кіл_ть_байтів, size_t кіл_ть_блоків, FILE *fp)

size_t fwrite(const void *буфер, size_t кіл_ть_б, size_t кіл_ть _блоків, FILE *fp)

У прототипі функції fwrite() параметр буфер являє собою покажчик на область пам'яті де містяться дані, що повинні бути записані у файл. Значення параметру кількість блоків (кіл_ть _блоків) визначає кількість блоків що підлягає зчитуванню або запису. Довжина блоків задається параметром кількість байтів. (Нагадаємо, що тип size_t визначений як ціле число без знака.) Вказівник fp є вказівником на раніше відкритий потік.

Функція fread() повертає кількість зчитаних блоків. Кількість зчитаних блоків може бути менше параметру блоків, якщо буде досягнуто кінець файлу або виникла помилка. Якщо не виникло помилки, це значення дорівнює параметру кількості блоків.

Приклад ілюструє спочатку запис трьох змінних типів double, int
та long у файл відкритий в бінарному режимі, а потім зчитує та виводить на екран числа. Необхідно звернути увагу на функцію sizeof, що забезпечує
визначення кожного типу даних.

#include <stdio.h> #include <stdlib.h> int main() {  
FILE *fp; double d = 12.23; int i = 101; long l = 123023L;  
if((fp=fopen("test", "w+b"))==NULL) { printf("Відбулась помилка! \n"); exit(1); } // якщо виникне помилка дамо повідомлення на екран
fwrite(&d, sizeof(double), 1, fp); fwrite(&i, sizeof(int), 1, fp); fwrite(&l, sizeof(long), 1, fp); // записуємо d, i, l
rewind(fp); //переводимо курсор на початок файлу
fread(&d, sizeof(double), 1, fp); fread(&i, sizeof(int), 1, fp); fread(&l, sizeof(long), 1, fp); // зчитуємо в тій послідовності, що й записали
printf("double=%5.4f int=%d long=%ld", d,i,l); //друкуємо d, i, l
fclose(fp); return 0; }  

Приклад ілюструє запис структури, що складається з двох полів.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <iostream> using namespace std; int main(void) {  
FILE *f; int i=0, j, t, n, pp; const int l=20; char sf[40]; struct STUDENT { char Name[l]; int Year; }; STUDENT stud;  
printf("Введіть ім’я файлу: "); gets(sf); f=fopen(sf, " wb+"); if(f!= NULL) {   //відкриває для запису бінарний потік
s11: strcpy(stud.Name,""); stud.Year=0; pp=1; //systen("clrscr"); i++; printf("Введіть запис [%d]: \n", i); printf("ПІБ студента -> ");  
do { gets(stud.Name); t=strlen(stud.Name); } while (t==0); //конструкція дозволяє забезпечити введення прізвища студента
for (j = t; j < l-2; j++) strcat(stud.Name," "); //додаємо додаткові пробіли, щоб мати однакову довжини = l
printf("Введіть дату народження-> "); cin >> stud.Year; //введення дати народження
fwrite(&stud, sizeof(struct STUDENT), 1, f); // записуємо запис у файл
s12: printf("Для продовження натисніть -> Enter, для виходу -> Esc \n",n);  
while (!kbhit()); // очікування натискання клавіші
if ((pp=getch())!=27) if (pp==13) goto s11; else goto s12; //зчитування та перевірна натиснутих клавіш за кодом натиснутої клавіші, Enter – 13 / Esc – 27
} fclose(f); return 0; }  

Приклад ілюструє зчитування записів, що записані за допомогою попередньої прикладу.

#include <stdio.h> using namespace std; int main(void) { FILE *f; int i; const int l=20; char sf[40]; struct STUDENT { char Name[l]; int Year; }; STUDENT stud;  
printf("Введіть ім’я файлу: "); gets(sf); f=fopen(sf, " rb+"); if(f!= NULL) {   //відкриття файлу в режимі зчитування
fseek(f,0,SEEK_END); //переводимо курсор в кінець файлу
int d = (int)(ftell(f)/sizeof(struct STUDENT)); //визначає кількість записів за формулою (кількість записаного)/(розмір структури одного запису)
fseek(f,0,SEEK_SET); //переведення курсору на початок файлу
for(i=0;i<d;i++) { fread(&stud, sizeof(struct STUDENT), 1, f); printf("Запис [%d]: %s %d \n",1+i,stud.Name, stud.Year); }  
rewind(f); //переведення курсору на початок файлу
i=0; while (!feof(f)) { i++; printf("\nПозиція курсору = %ld\n ", ftell(f)); fread(&stud, sizeof(struct STUDENT), 1, f); printf("Запис [%d]: %s %d \n",i,stud.Name, stud.Year); }  
} fclose(f); return 0; }  

Результат:

Запис [0]: Пузій П.П. 1979

Запис [1]: Петренко П.А. 1980

Позиція курсору = 0

Запис [1]: Пузій П.П. 1979

Позиція курсору = 24

Запис [2]: Петренко П.А. 1980

Позиція курсору = 48

Запис [3]: Петренко П.А. 1980


Функції fscanf() та fprintf()

Для зчитування та запису у файл за визначеним форматом використовують функції fscanf() та fprintf(). Як правило використовуються для файлів відкритих у текстовому режимі.

Загальний вигляд функції зчитування:

int count = fscanf(FILE *fp, char format, a,b,...)

Загальний вигляд функції запису:

int count = fprintf(FILE *fp, char format, a,b,...)

Параметри функцій:

value – змінна в яку буде зчитано інформацію з файлу;

count – кількість записаних (зчитаних) даних;

fp – вказівник на раніше відкритий потік.

size – максимальна кількість зчитаних даних;

a,b,.. – змінні для запису/зчитування даних у файл.

format – формат зчитування (запису) даних, наприклад "%d";

При форсуванні формату зчитування використовуються наступні специфікації:

%d – ціле число;

%f – дійсне число;

%s – символьний рядок;

%c – символ;

%u – безнакове ціле число;

%[множина символів, що необхідно зчитати]

\r – повернення курсору на початок рядка;

\n – перехід на новий рядок.

Для визначення довжини зчитує мого результату задається його розмір, наприклад %2d, %4.2f, %20s,

Формат зчитування та запису повинен співпадати, що забезпечує коректне виконання операцій при їх виконанні.

Приклад ілюструю зчитування та запис з використанням функцій fscanf() та fprintf().

#include <stdio.h> using namespace std; int main() {  
FILE *f; char str[80]; f=fopen("c:\\test.txt", " w+"); if(f!= NULL) {  
int fa = 1; for (int i=1; i<=10; ++i) { fprintf(f, "i=%d, i^2=%d, factorial(%d)=%d\n", i, i*i, i, fa*=i); }  
rewind(f);  
int n, sq, L, fact; while (!feof(f)) { fscanf(f,"i=%d, i^2=%d, factorial(%d)=%d ", &n, &sq, &L, &fact); //printf("i=%d, i^2=%d, factorial(%d)=%d \n", n, sq, L, fact); //printf("i=%d, factorial=%d \n", n, fact); printf("factorial(%d)=%d \n", n, fact); }  
} else printf("Error \n"); fclose(f); return 0; }  

Результат запису у файл:

Результат зчитування з файлу:

Приклад: Необхідно прочитати з заданого файлу матрицю, розмірність якої записана в першому рядку. Потім записана матриця. Після йде символьний рядок «25 54.32E-1 Thompson 56789 0123 56», що зчитується за заданим форматом у шість параметрів. В кінці файлу задано символьний рядок, що необхідно зчитати з заду на перед. Приклад демонструє використання функцій зчитуваня у форматному вигляді та переведення курсору.

Вхідний файл:

3 та 4 задано розмірність матриці 3х4.

#include <stdio.h> int main() { int i, j, d, n=0, m=0, k=0; long L, p; float x, y; char str1[10], str2[4]; char ch; float a[50][50]; FILE *f;  
f=fopen("c:\\fm.txt", "r+"); if(f!= NULL) { //відкриваємо файл для зчитування в текстовому режимі
fscanf(f,"%d",&n); fscanf(f,"%d",&m); // зчитуємо по одному цілі числа, що визначають розмірність матриці
for(i=0;i<n;i++) for(j=0;j<m;j++) fscanf(f,"%f",&a[i][j]); //зчитуємо дійсні числа по одному в елементи матриці
printf("Матриця A[%d,%d]:\n",n,m); for(i=0;i<n;i++) { for(j=0;j<m;j++) printf(" %3.1f ",a[i][j]); printf("\n"); } //друкуємо сформовану матрицю
printf("Позиція курсору = %ld\n ",ftell(f)); //визначаємо поточну позицію курсору у файлі
k=fscanf(f, "%d%f%9s%2d%f%*d %3[0-9]", &i, &x, str1, &j, &y, str2); //зчитуємо у змінні дані за заданими параметрами
printf("Converted %d fields:\n i = %d\n" " x = %5.2f\n str1 = %s\n" " j = %d\n y = %5.2f\n str2 = %s\n", k, i, x, str1, j, y, str2); //виводимо зчитані дані з файлу на екран
L = ftell(f); printf("Позиція курсору = %ld\n ",L); //визначаємо поточну позицію курсору у файлі
fseek(f,0,SEEK_END); // переводимо курсор в кінець файлу
d = ftell(f)-L; printf("Довжина останнього " " символьного рядка = %ld\n ",d); // визначаємо довжину останнього символьного рядка з різниці між усіх символів (ftell(f)) – поточної позиції, що визначили до того (L)
for(int i = 1;i < d;i++) { fseek(f,-i,SEEK_END); ch = getc(f); putchar(ch); } /зчитуємо по одному символу та виводимо на екран останній символьний рядок, для цього вказуємо перед зчитуванням вказуємо позицію командою fseek(f,-i,SEEK_END) – кожен раз функція вказує зміщення з кінця файлу.
printf("\n Позиція курсору = %ld\n ", ftell(f)); //визначаємо поточну позицію курсору у файлі
for(int i = 1;i < d;i++) { ch = getc(f); printf("Символ [%d] = %c\n ",ftell(f), ch); } /зчитуємо по одному символу символьний рядок та виводимо на екран позицію символу.
} fclose(f); }  

Результат виконання:

Матриця A[3,4]:

3.4 4.5 5.4 2.1

3.4 56.0 6.0 9.1

5.4 6.0 3.0 3.5

Позиція курсору = 47

Converted 6 fields:

i = 25

x = 5.43

str1 = Thompson

j = 56

y = 789.00

str2 = 56

Позиція курсору = 83

Довжина останнього символьного рядка = 13

.++C evol I

Позиція курсору = 85

Символ [86] = I

Символ [87] =

Символ [88] = l

Символ [89] = o

Символ [90] = v

Символ [91] = e

Символ [92] =

Символ [93] = C

Символ [94] = +

Символ [95] = +

Символ [96] =.

Символ [96] =


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: