- •Лекція № 11 обмін даними з файлами
- •1. Файли і потоки, буферизація даних
- •2. Групи функцій для роботи з потоками
- •3. Відкриття/закриття потоків
- •3.1. Відкриття потоків.
- •4. Стандартні потоки, перескерування потоків
- •5. Функції потокового введення/виведення даних
- •5.1. Посимвольний обмін даними
- •5.2. Файловий обмін рядками символів
- •5.3. Обмін блоками даних
- •5.4. Форматне введення/виведення даних
- •6. Встановлення поточної позиції файлу
- •7. Функції аналізу помилок
- •8. Керування буферизацією даних
- •9. Витирання та перейменування файлів
- •10. Інші засоби для роботи з файлами
- •10.2. Низькорівневе звертання до файлів
9. Витирання та перейменування файлів
У багатьох практичних задачах потрібно редагувати або частково змінювати вміст файлу. Здебільшого процес редагування файлу включає таку послідовність дій:
-
відкрити для читання файл, що має бути змінений;
-
створити новий тимчасовий файл для запису;
-
у новий файл переписати вміст базового файлу, виконавши потрібні зміни та доповнивши його необхідною інформацією;
-
закрити обидва файли;
-
витерти файл, який редагувався;
-
надати новоствореному файлу ім'я базового.
Конкретні реалізації задач редагування вмісту файлу можуть мати свої особливості. Наприклад, базовий файл можна не витирати, а зберігати зі зміненим іменем чи розширенням (загальноприйнятою є заміна розширення на *.bас - bac-версія). Деколи після завершення роботи витирають тимчасовий файл або переписують його в інший каталог тощо.
Для програмування кроків 5 та 6 наведеної схеми редагування файлів доцільно використовувати бібліотечні функції витирання та перейменування файлів, оголошені разом з іншими функціями файлового обміну в <stdio. h>.
Функція
int remove (char * fname);
витирає файл з іменем fname (правила запису імені файлу такі ж, як і для функції fopen()). За умови успішного витирання файлу remove () повертає нуль, а в разі невдачі - ненульове значення.
У Borland C remove () організовано як макрос, який викликає функцію unlink (), що власне реалізує процес витирання файла:
int unlink (char* fname);
Функція unlink () не підтримується стандартом мови С.
Зміну імені файла виконує функція
int rename (char* oldfname, char* newfname);
У разі успішного виконання функція повертає нуль, а файлу, ім'я якого задається параметром oldfname, присвоюється нове ім'я - newfname.
У програмах, що реалізуються в середовищі Borland C, перейменування файлів виконується за правилами MS DOS. Важливо, щоб на момент перейменування у каталозі не було іншого файлу з іменем newfname, бо тоді ім'я файлу не змінюється, а функція повертає значення, що не дорівнює нулю. Тому в процесі редагування файлу спочатку витирають або перейменовують базовий файл, а вже потім його ім'я надають новоствореному.
Всі функції витирання та перейменування файлів працюють тільки зі закритими файлами.
Створення нових і тимчасових файлів пов'язане з необхідністю перевірки, чи існує інший файл з іменем, яке повинен отримати новостворений файл. Якщо такий контроль не здійснювати, то можна випадково затерти наявний однойменний файл.
Альтернативним вирішенням даної проблеми є використання функції, що генерує ім'я файлу, яке буде унікальним для поточного активного каталогу:
char* tmpnam (char* fname);
Єдиним параметром tmpnam () є вказівник на масив символів, в який буде записано згенероване ім'я. Розмірність масиву fname повинна бути не меншою за значення макроконстанти L_tmpnam (13 символів). Якщо замість fname підставити значення NULL, то згенероване функцією ім'я буде записане у спеціальну внутрішню змінну, адресу якої поверне функція.
У Borland C унікальні імена створюються за таким правилом: якщо в активному каталозі відсутній файл з іменем tmpl.$$$, то це буде першим згенерованим ім'ям, інакше послідовно перевіряються імена tmp2.$$$, tmp3.$$$ і т.д. Кожен виклик функції tmpnam () у програмі генерує наступне за порядковим номером ім'я файлу.
У разі успішного виконання tmpnam () повертає адресу першого символу зге-нерованого імені файлу. Якщо ж унікальне ім'я згенерувати не вдалось, то функція повертає NULL.
Проілюструємо застосування описаних вище функцій прикладом програми, яка виконує редагування вмісту файлу. Програма реалізує таку задачу: в заданому текстовому файлі треба доповнити кожну цифру словесним найменуванням (тобто відповідним чисельником), записаним у круглих дужках. Відредагованому файлу треба надати ім'я, яке мав базовий файл.
/**************************************************************************/
/* Доповнення файлу найменуваннями цифрових символів */
/**************************************************************************/
#include <stdio.h>
#include <ctype.h>
int main (void)
{
FILE * fold, *ftmp; /* вказівники базового та нового файлів */
char foldname[13], ftmpname[13];
int symb;
char * number[] = { "нуль", "один", "два", "три", "чотири",
"п'ять", "шість", "сім", "вісім", "дев'ять"};
printf ("Файл для заміни - ");
gets(foldname);
if ( (fold= fopen(foldname,"rt"))-== NULL ) {
printf ("Помилка в імені файла - %s \n", foldname);
return 0;
}
tmpnam (f tmpname); /* генерування унікального імені файла */
if ((ftmp = fopen(ftmpname,"wt"))== NULL ) { printf ("He можна створити новий файл");
return 0; }
while ((symb = getc(fold) ) != EOF ) { /* цикл редагування файла */
putc(symb, ftmp);
if ( isdigit(symb) ) /* якщо зустрілась цифра, то виводиться */
fprintf (ftmp, "(%s)", number[symb-'0']); /* її назва */
}
fcloseall(); /* закриття файлів */
if (remove (foldname )== 0) { /* витирання початкового файла */
rename (f tmpname, foldname); /* перейменування нового файла */
printf("Файл %s відредаговано.\n", foldname);
} else
printf("Створено новий файл - %s \n", ftmpname);
return 0; }
Файл, призначений для тимчасового використання, можна створити за допомогою функції
FILE * tmpfile (void);
Вона відкриває тимчасовий файл у режимі бінарного читання/запису ("w+b"). Файл отримує унікальне ім'я згідно з tmpnam (). Треба пам'ятати, що створюється тимчасовий файл - він буде автоматично витертий після закриття чи завершення роботи програми.
Функція tmpfile () повертає вказівник на потік, пов'язаний зі створеним тимчасовим файлом, або NULL, якщо файл відкрити не вдалось.