- •Потоки та файли
- •Основи файлової системи
- •Закриття файлу
- •Запис символу: 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 начало_отсчета);
- •Виведення у файловий потік
- •Запис у вихідний файловий потік
- •Читання з вхідного файлового потоку
- •Перевірка помилок при виконання файлових операцій
- •Виконання операцій читання і запису
- •Зауваження та рекомендації
Функції fprinf () і fscanf ()
Крім основних функцій введення/виведення, про які йшла мова, в системі введення/виведення мови С також є функції fprintf() і fscanf(). Ці дві функції, за винятком того, що призначені для роботи з файлами, ведуть себе точно так само, як і printf() і scanf(). Прототипи функцій fprintf() іfscanf () наступні:
int fprintf (FILE * pf, const char * управляющая_строка, ...); int fscanf (FILE * pf, const char * управляющая_строка, ...);
де pf – покажчик файлу, що повертається в результаті виклику fopen(). Операції введення/виведення fprintf() і fscanf() виконують з тим файлом, на який вказує pf.
Як приклад пропонується розглянути наступну програму, яка читає з клавіатури рядок і ціле значення, а потім записує їх у файл на диску, а ім'я цього файлу – TEST. Після цього програма читає цей файл і виводить інформацію на екран. Після запуску програми перевірте, яким вийде файл TEST. Як ви і побачите, в ньому буде цілком легкий для читання текст.
int main (void) { FILE * fp; char s [80]; int t; if ((fp = fopen ("test", "w")) == NULL) { printf ("Помилка відкриття файлу. \ n"); exit (1); } printf ("Введіть рядок і число:"); fscanf (stdin, "% s% d", s, & t); / * читати з клавіатури * / fprintf (fp, "% s% d", s, t); / * писати в файл * / fclose (fp); if ((fp = fopen ("test", "r")) == NULL) { printf ("Помилка при відкритті файлу. \ n"); exit (1); } fscanf (fp, "% s% d", s, & t); / * читання з файлу * / fprintf (stdout, "% s% d", s, t); / * виведення на екран * / return 0; }
Зауваження. Хоча читати різносортні дані з файлів на дисках і писати їх у файли, розташовані також на дисках, часто найлегше саме з допомогою функцій fprintf() і fscanf(), але це не завжди найефективніший спосіб виконання операцій читання і запису. Оскільки дані в форматі ASCII записуються так, як вони повинні з'явитися на екрані (а не в двійковому вигляді), то кожен виклик цих функцій пов'язаний з певними накладними витратами. Тому, якщо треба дбати про розмір файлу або швидкість, то, швидше за все, доведеться використовувати fread() і fwrite().
Введення-виведення при прямому доступі: функція fseek ()
При прямому доступі можна виконувати операції введення/виведення, використовуючи систему введення/виведення мови С і функцію fseek(), яка встановлює покажчик поточної позиції у файлі. Ось прототип цієї функції:
Int fseek (file * pf, long int коліч_байт, int начало_отсчета);
Тут pf - це покажчик файлу, що повертається в результаті виклику функції fopen(), коліч_байт - кількість байтів, рахуючи від начало_отсчета, воно визначає нове значення покажчика поточної позиції, а початок відліку - це один з таких макросів:
Початок файлу - SEEK_SET Поточна позиція - SEEK_CUR Кінець файлу - SEEK_END
Тому, щоб отримати у файлі доступ на відстані коліч_байт байтів від початку файлу, начало_отсчета повинна дорівнювати SEEK_SET. Щоб при доступі відстань відраховується від поточної позиції, використовуйте макрос SEEK_CUR, а щоб при доступі відстань відраховується від кінця файлу, потрібно вказувати макрос SEEK_END. При успішному завершенні своєї роботи функція fseek () повертає нуль, а в разі помилки - ненульове значення.
У наступній програмі показано, як використовується fseek (). Тут в певному файлі відшукує деякий байт, а потім відображає його. У командному рядку потрібно вказати ім'я файлу, а потім потрібний байт, тобто відстань в байтах від початку файлу.
# include <stdio.h> # include <stdlib.h> int main (int argc, char * argv []) { FILE * fp;
if (argc! = 3) { printf ("Синтаксис: SEEK <ім'я файлу> <байт> \ n"); exit (1); }
if ((fp = fopen (argv [1], "rb "))== NULL) { printf ("Помилка при відкритті файлу. \ n"); exit (1); }
if (fseek (fp, atol (argv [2]), SEEK_SET)) { printf ("Seek error. \ n"); exit (1); }
printf ("У% ld-м байті міститься% c. \ n", atol (argv [2]), getc (fp)); fclose (fp);
return 0; }
Функцію fseek() можна використовувати для доступу всередині багатьох значень одного типу, просто множачи розмір даних на номер елемента, який вам потрібен. Наприклад, припустимо, є список розсилки, який складається з структур типу addr (визначених раніше). Щоб отримати доступ до десятого адресою у файлі, в якому зберігаються адреси, використовуйте наступний оператор:
fseek (fp, 9 * sizeof (struct addr), SEEK_SET);
Поточне значення індексу поточної позиції у файлі можна визначити за допомогою функції ftell (). Ось її прототип:
long int ftell (FILE * pf);
Функція повертає поточне значення покажчика поточної позиції у файлі, пов'язаному з покажчиком файлу pf. При невдалому результаті вона повертає -1. Зазвичай прямий доступ може знадобитися лише для двійкових файлів. Причина тут проста - тому що в текстових файлах можуть виконуватися перетворення символів, то може і не бути прямого відповідності між тим, що знаходиться у файлі і тим байтом, до якого потрібен доступ. Єдиний випадок, коли треба використовувати fseek() для текстового файлу - це доступ до тієї позиції, яка була вже знайдена за допомогою ftell(); такий доступ виконується за допомогою макросу SEEK_SET, використовуваного в якості початку відліку.
Зауваження: навіть якщо у файлі знаходиться один тільки текст, все одно цей файл при необхідності можна відкрити і в двійковому режимі. Ніякі обмеження, пов'язані з тим, що файли містять текст, до операцій прямого доступу не відносяться. Ці обмеження стосуються лише до файлів, відкритим в текстовому режимі.