- •Потоки та файли
- •Основи файлової системи
- •Закриття файлу
- •Запис символу: putc() і fputc()
- •Читання символу: getc() і fgetc()
- •Використання fopen(), getc(), putc(), і fclose()
- •Використання feof ()
- •Введення/виведення рядків: fputs () і fgets ()
- •Int fputs (const char * cmp, file * pf); char * fgets (char * cmp, int довжина, file * pf);
- •Функція rewind ()
- •Функція ferror ()
- •Функції fprinf () і fscanf ()
- •Введення-виведення при прямому доступі: функція fseek ()
- •Int fseek (file * pf, long int коліч_байт, int начало_отсчета);
- •Виведення у файловий потік
- •Запис у вихідний файловий потік
- •Читання з вхідного файлового потоку
- •Перевірка помилок при виконання файлових операцій
- •Виконання операцій читання і запису
- •Зауваження та рекомендації
Функція rewind ()
Функція rewind() встановлює покажчик поточної позиції у файлі на початок файлу, вказаного як аргумент цієї функції. Іншими словами, функція rewind() виконує "перемотування" (rewind) файлу. Ось її прототип:
void rewind (FILE * pf);
Щоб познайомитися з rewind(), змінимо програму з попереднього розділу таким чином, щоб вона відображала вміст файлу відразу після його створення. Щоб виконати відображення, програма після завершення введення "перемотує" файл, а потім за допомогою fback() читає його з самого початку. Зверніть увагу, що зараз файл необхідно відкрити в режимі читання/запису, використовуючи як аргумент, що задає режим, рядок "w+".
# include <stdio.h> # include <stdlib.h> # include <string.h> int main (void) { char str [80]; FILE * fp; if ((fp = fopen ("TEST", "w +"))== NULL) { printf ("Помилка при відкритті файлу. \ n"); exit (1); } do { printf ("Введіть рядок (порожню – для виходу): \ n"); gets (str); strcat (str, "\ n"); / * введення роздільник рядків * / fputs (str, fp); } while (* str! = '\n'); / * Тепер виконується читання і відображення файлу * / rewind (fp); / * встановити покажчик поточної позиції на початок файлу. * / while (! feof (fp)) { fgets (str, 79, fp); printf (str); } return 0; }
Функція ferror ()
Функція ferror() визначає, чи відбулася помилка під час виконання операції з файлом. Прототип цієї функції наступний:
int ferror (FILE * pf);
де pf – допустимий покажчик файла. Вона повертає значення true (істина), якщо під час останньої операції з файлом сталася помилка, в іншому ж випадку вона повертає false (неправда). Так як при будь-якої операції з файлом встановлюється свою умову помилки, то після кожної такої операції слід одразу викликати ferror(), а інакше дані про помилку можуть бути втрачені.
У наступній програмі показано застосування ferror(). Програма видаляє табуляції з файлу, замінюючи їх відповідною кількістю пробілів. Розмір табуляції визначається макросом TAB_SIZE. Зверніть увагу, що ferror() викликається після кожної операції з файлом. При запуску цієї програми вказуйте в командному рядку імена вхідного і вихідного файлів.
/ * Програма замінює в текстовому файлі символи табуляції пробілами і відстежує помилки. * / # include <stdio.h> # include <stdlib.h> # define TAB_SIZE 8 # define IN 0 # define OUT 1 void err (int e); int main (int argc, char * argv []) { FILE * in, * out; int tab, i; char ch; if (argc! = 3) { printf ("Синтаксис: detab <вхідний_файл> <вихідний файл> \ n"); exit (1); } if ((in = fopen (argv [1], "rb "))== NULL) { printf ("Не можна відкрити% s. \ n", argv [1]); exit (1); } if ((out = fopen (argv [2], "wb "))== NULL) { printf ("Не можна відкрити% s. \ n", argv [2]); exit (1); } tab = 0; do { ch = getc (in); if (ferror (in)) err (IN); / * Якщо знайдена табуляція, виводиться відповідне число пробілів * / if (ch == '\ t') { for (i = tab; i <8; i + +) { putc ('', out); if (ferror (out)) err (OUT); } tab = 0; } else { putc (ch, out); if (ferror (out)) err (OUT); tab + +; if (tab == TAB_SIZE) tab = 0; if (ch == '\ n' | | ch == '\ r') tab = 0; } } While (! Feof (in)); fclose (in); fclose (out); return 0; } void err (int e) { if (e == IN) printf ("Помилка при вводі. \ n"); else printf ("Помилка при виведенні. \ n"); exit (1); }
Стирання файлів
Функція remove() стирає вказаний файл. Ось її прототип:
int remove (const char * ім'я_файлу);
У разі успішного виконання ця функція повертає нуль, а в іншому випадку – ненульове значення.
Наступна програма стирає файл, вказаний в командному рядку. Однак спочатку вона дає можливість передумати. Утиліта, подібна до цієї, може стати в нагоді комп'ютерним користувачам-новачкам.
int main (int argc, char * argv []) { char str [80]; if (argc! = 2) { printf ("Синтаксис: xerase <ім'я файлу> \ n"); exit (1); } printf ("Стерти% s? (Y / N):", argv [1]); gets (str); if (toupper (* str) == 'Y') if (remove (argv [1])) { printf ("Не можна стіреть файл. \ n"); exit (1); } return 0; }
Дозапис потоку
Для дозапису вмісту вивідного потоку в файл застосовується функція fflush (). Ось її прототип:
int fflush (FILE * pf);
Ця функція записує всі дані, що знаходяться в буфері в файл, який вказаний за допомогою PF. При виконанні функції fflush() з порожнім (null) покажчиком файлу pf буде виконана дозапис в усі файли, відкриті для виведення.
Функції fread () і fwrite ()
Для читання і запису даних, тип яких може займати більше 1 байта, у файловій системі мови С є дві функції: fread() і fwrite(). Ці функції дозволяють читати і записувати блоки даних будь-якого типу. Їх прототипи наступні:
size_t fread (void * буфер, size_t коліч_байт, size_t лічильник, FILE * pf); size_t fwrite (const void * буфер, size_t коліч_байт, size_t лічильник, FILE * pf);
Для fread() буфер – це покажчик на область пам'яті, в яку будуть прочитані дані з файлу. А для fwrite() буфер – це покажчик на дані, які будуть записані у файл. Значення лічильник визначає, скільки зчитується або записується елементів даних, причому довжина кожного елемента в байтах дорівнює коліч_байт. (Пригадайте, що тип size_t визначається як один з різновидів цілого типу без знака.) І, нарешті, pf – це покажчик файлу, тобто на вже відкритий потік.
Функція fread() повертає кількість прочитаних елементів. Якщо досягнуто кінець файлу або сталася помилка, то повертається значення може бути менше, ніж лічильник. А функція fwrite() повертає кількість записаних елементів. Якщо помилка не відбулася, то повертається результат буде дорівнює значенню лічильник.
Як тільки файл відкритий для роботи з двійковими даними, fread() і fwrite() відповідно можуть читати і записувати інформацію будь-якого типу. Наприклад, наступна програма записує в дисковий файл дані типів double, int і long, a потім читає ці дані з того ж файлу. Зверніть увагу, як у цій програмі при визначенні довжини кожного типу даних використовується функція sizeof().
int main (void) { FILE * fp; double d = 12.23; int i = 101; long l = 123023L; if ((fp = fopen ("test", "wb +"))== NULL) { printf ("Помилка при відкритті файлу. \ n"); exit (1); } fwrite (& d, sizeof (double), 1, fp); fwrite (& i, sizeof (int), 1, fp); fwrite (& l, sizeof (long), 1, fp); rewind (fp); fread (& d, sizeof (double), 1, fp); fread (& i, sizeof (int), 1, fp); fread (& l, sizeof (long), 1, fp); printf ("% f% d% ld", d, i, l); fclose (fp); return 0; }
Як видно з цієї програми, як буфер можна використовувати (і часто саме так і роблять) просто пам'ять, в якій розміщена змінна. У цій простій програмі значення, які повертаються функціями fread() і fwrite(), ігноруються. Однак на практиці ці значення необхідно перевіряти, щоб виявити помилки.
Одним з найбільш корисних застосувань функцій fread() і fwrite() є читання і запис даних користувача типів, особливо структур. Наприклад, якщо визначена структура
struct struct_type { float balance; char name [80]; } Cust;
то наступний оператор записує вміст cust у файл, на який вказує fp:
fwrite (&cust, sizeof (struct struct_type), 1, fp);