Особливості обробки файлів у с-програмах Організація роботи з файлами
У мові С файл розглядається як потік послідовності байтів. Робота з файлом здійснюється через файловий покажчик, який ідентифікує конкретний дисковий файл і використовується потоком у всіх операціях з цим файлом. У С-програмах файловий покажчик - це змінна-покажчик стандартного типу FILE, який містить різноманітні відомості про файл: його ім'я, розташування на диску, режим роботи з файлом, покажчик поточної позиції і т. ін.:
FILE *filename;
Тип FILE означено у бібліотеці <stdio.h>. Тому, якщо в програмі передбачається робота з файлами даних, цей заголовний файл слід підключити до програми.
Наприклад,
#include <stdio.h>
FILE *f; // оголошення файлового покажчика у С-програмах
Зв'язування оголошеного файлового покажчика з фізичним файлом на диску відбувається при відкритті файлу.
У С-програмах для відкриття файлу використовується функція fopen():
FILE *fopen(const char *filename, const char *mode);
Тут параметр filename - це рядок, що визначає повне ім’я фізичного файлу, який відкривається. Цей параметр може містити специфікацію шляху до файлу у файловій структурі диску. Параметр mode – це рядок символів, що визначає потрібний статус (режим) відкриття файлу. Можливі значення параметра mode наведені у табл. 1.
Таблиця 1. Специфікатори режиму відкриття файлів
|
Режим |
Призначення |
|
r |
відкрити існуючий файл тільки для зчитування даних (читання) |
|
w |
створити файл тільки для запису даних (якщо відповідний фізичний файл існує, то його вміст втрачається) |
|
a |
створитиновий файл або відкритиіснуючийфайл длязапису даних в кінецьфайлу(дозапису) |
|
r+ |
відкритиіснуючийфайл длязчитуванняізапису даних |
|
w+ |
створити новий файл для зчитування і запису даних (якщо відповідний фізичний файл існує, то його вміст втрачається) |
|
a+ |
створитиновий файл або відкритиіснуючийфайлдлязчитування ізаписування даних в кінецьфайлу(дозапису) |
До зазначених специфікаторів наприкінці чи перед знаком “+” може дописуватись символ-специфікатор типу файла: “t” – для текстових файлів, “b” – для бінарних (двійкових) файлів. Наприклад,
FILE *f;
f = fopen("D:\file.txt", "w+t"); // створення текстового файла в режимі читання- запису
Слід зазначити, що рядки, подібні "w+t" можуть бути представлені і у вигляді "wt+".
Необхідність у використанні суфікса t є не у всіх ОС, а тільки у тих, у яких є відмінності в роботі з текстовими і бінарними файлами, зокрема, в MS-DOS, Windows (в Unix таких відмінностей немає).
У С-програмах відкрити файл можна і при створенні відповідного файлового потоку. Наприклад,
FILE *f = fopen("h:\file.txt", "r");
У разі вдалого відкриття файлу функція fopen() повертає покажчик на структуру типу FILE, що описує параметри відкритого файлу. Цей покажчик потім використову-ється для звертання до файлу у всіх файлових операціях.
Якщо файл відкрити не вдалося, наприклад, при спробі відкрити для читання неіснуючий файл, то повертається нульовий покажчик NULL. При цьому глобальна системна змінна errno, описана в стандартному заголовному файлі <errno.h>, містить числовний код помилки. За необхідності цей код можна вивести, щоб отримати додаткову інформацію. Наприклад,
FILE *f;
if ((f = fopen("h:\file.txt", "r"))== NULL)
{ printf("Error opening file with code %d \n", errno);
exit(1); // закінчити роботу програми
};
Замість коду помилки можна вивести системне повідомлення про помилку (на англійській мові) і додати до нього будь-який текст. Така можливість надається при використанні функції perror. Наприклад,
FILE *f;
if ((f = fopen("h:\file.txt", "r"))== NULL)
{ perror("Не могу открыть файл на чтение ");
return 1; // завершити роботу програми з кодом помилки
}
Функція perror друкує спочатку задане повідомлення про помилку, а потім, після двокрапки, системне повідомлення. Наприклад,
Не могу открыть файл на чтение: No such file or directory
Для уникання помилок після відкриття файла слід перевіряти, чи насправді файл відкрився.
Обробка файлу полягає у реалізації операцій зчитуванню даних із файлу або запису даних у файл. Операції читання та запису завжди виконуються, починаючи з поточної позиції у файлі. Початкова позиція встановлюється при відкритті файлу і може відповідати початковому або кінцевому байту файла в залежності від режиму відкриття файлу. При відкритті файлу в режимах читання або запису покажчик поточної позиції встановлюється на початок файлу (на його початковий байт), при відкритті в режимі дозапису - в кінець файлу (за останнім його байтом). При виконанні кожної операції читання або запису покажчик переміщується на нову поточну позицію у відповідності із числом записаних або прочитаних байтів.
У мові С передбачено декілька різновидів засобів файлового введення-виведення: символьні, рядкові, блокові, форматовані. Їх прототипи містяться в заголовному файлі stdio.h.
При виконанні кожної операції введення/виведення покажчик поточної позиції файлу зміщується на одну позицію в сторону кінця файлу. В якийсь момент він досягає кінця файлу. Для перевірки цього факту використовується функція feof():
int feof(FILE *stream);
Ця функція повертає значення, відмінне від нуля (true), якщо всі елементи файлу прочитані і покажчик файлу вказує на маркер кінця файлу (знаходиться за останнім елементом файлу) або файл після відкриття виявився порожнім; у всіх інших випадках функція повертає значення false (0). Використовуючи функцію feof() у циклі з передумовою, можна читати вміст файлу, поки не буде досягнутий його кінець:
while (! feof(f))
{ …
};
Логічним закінченням роботи з відкритим файлом є його закриття. Для закриття файла у мові С служить функція fclose():
