- •Лекція № 11 обмін даними з файлами
- •1. Файли і потоки, буферизація даних
- •2. Групи функцій для роботи з потоками
- •3. Відкриття/закриття потоків
- •3.1. Відкриття потоків.
- •4. Стандартні потоки, перескерування потоків
- •5. Функції потокового введення/виведення даних
- •5.1. Посимвольний обмін даними
- •5.2. Файловий обмін рядками символів
- •5.3. Обмін блоками даних
- •5.4. Форматне введення/виведення даних
- •6. Встановлення поточної позиції файлу
- •7. Функції аналізу помилок
- •8. Керування буферизацією даних
- •9. Витирання та перейменування файлів
- •10. Інші засоби для роботи з файлами
- •10.2. Низькорівневе звертання до файлів
6. Встановлення поточної позиції файлу
Високорівневий потокоорієнтований обмін даними з файлами організовано як передавання необхідної послідовності байтів. Кожна операція введення даних з файлу, відкритого для читання, пов'язана зі зміщенням внутрішнього покажчика (індикатора) поточної позиції файлу на відповідну кількість байтів. Файл, відкритий для запису (режим відкриття "w"), спочатку порожній, а в процесі запису покажчик поточної позиції автоматично встановлюється за останнім записаним байтом. Якщо ж файл відкривається для доповнення (режим відкриття "а"), то вміст файла зберігається, а покажчик поточної позиції встановлюється перед маркером кінця файла.
Хоча в процесах обміну даними послідовне зчитування з файлу чи послідовний запис у файл застосовуються найчастіше, все ж у багатьох задачах потрібно керувати значенням покажчика поточної позиції файлу. Це, зокрема, дає змогу виконувати операції введення/виведення даних, починаючи зі заданого байта файлу.
Основною функцією позиціювання потоку даних є функція
int fseek (FILE* fp, long offset, int base);
Функція fseek() встановлює покажчик поточної позиції файлу, пов'язаного з потоком fp, відповідно до значень, заданих параметрами offset і base. Параметр offset, який має тип довгого цілого, задає кількість байтів, на які треба пересунути поточну позицію файлу. Якщо offset>0, то покажчик поточної позиції зсувається у напрямку кінця файлу, коли ж offset < 0, то покажчик зсувається до початку файлу. Параметр base задає базис, відносно якого здійснюється переміщення поточної позиції. Він може набувати значення однієї з трьох макроконстант:
-
SEEK_SET (у Borland C ця макроконстанта має значення 0) - за базис береться початок файлу;
-
SEEK_CUR (або 1) - за базис береться поточна позиція файлу;
-
SEEK_END (або 2) - за базис береться кінець файлу.
-
У разі успішного виконання функція fseek () повертає нуль, а в разі виникнення помилки позиціювання - ненульове значення.
Наступне звертання встановлює покажчик поточної позиції на початок файлу, пов'язаного з потоком frw:
fseek(frw, OL, SEEK_SET);
Щоб встановити покажчик поточної позиції бінарного файла, заповненого двійковими кодами дійсних чисел, перед десятим елементом, рахуючи від кінця файлу, треба викликати функцію fseek() з такими параметрами:
fseek(fdn, 10*sizeof(double), SEEK_END);
Ще одним способом швидкого переміщення покажчика поточної позиції відкрито файла на початок цього файла є використання функції
void rewind (FILE* fp);
Значення покажчика поточної позиції файла можна отримати через функцію
long ftell (FILE* fp);
Якщо потік fp відкрито в бінарному режимі, то значення, яке повертає ftell () дорівнює кількості байтів від початку файлу до його поточної позиції, зафіксованої у покажчику. Для текстових потоків це значення може бути неточним через перетворення символів кінця рядка. У разі помилки виконання функція ftell() повертає -1.
Зберегти значення поточної позиції файлу можна також за допомогою функції
int fgetpos (FILE* fp, long* fpos);
Функція записує в змінну, адресу якої задає вказівник fpos, значення покажчика поточної позиції файлу, пов'язаного з потоком fp. Повертає нуль у разі успішного її завершення і ненульове значення - у разі виникнення помилки.
Для відновлення значення поточної позиції файлу, збереженого раніше через звертання до fgetpos (), призначена функція
int fsetpos (FILE* fp, long* fpos);
параметри і значення якої такі самі, як і в попередньої функції.
Якщо потік відкрито для запису й читання одночасно (режим відкриття включає символ '+'), то, щоб перейти від операцій запису до операцій читання або навпаки, треба обов'язково між цими операціями викликати одну з функцій позиціювання: rewind (), fseek () або fsetpos ().
Проілюструємо використання описаних функцій позиціювання на прикладі функції FileSize (), яка визначає розмір (у байтах) файлу, відкритого в бінарному режимі.
/* Визначення розміру заданого файлу */
long FileSize (FILE * fz )
{
long fsize, fpos;
fgetpos (fz, &fpos); /* збереження поточної позиції файлу */
fseek (fz, 0L, SEEK_END); /* перехід у кінець файлу */
fsize=ftell(fz); /* розмір відповідає зміщенню */
fsetpos (fz, &fpos); /* повернення вказівника на попередню */
/* позицію */
return fsize;