3.3.1          Відкриття та закриття файлів

Окрім функцій для доступу до файлів як до потоків, Turbo С включає велику групу функцій префіксного доступу до файлів, або, як інколи кажуть, системних викликів, чи процедур нижнього рівня (Low Level File I/O Rutines). Префіксні функції не виконують додаткової буферизації інформації і відразу звертаються до функцій MS-DOS.

Префіксне відкриття файлу виконують дві функції бібліотеки Turbo С: ореn() та _ореn(). Перша з них максимально наближена до однойменного системного виклику ОС UNIX, друга є специфічною для MS-DOS формою префіксного відкриття файлу. Обидві функції звертаються до одних і тих функціональних викликів MS-DOS: відкриття файлу (АН=3Dh); створення файлу (АН=3Ch), якщо задане створення файлу. Далі наведена специфікація розглянутих функцій.

#include <io.h>
int open( const char *pathname, int access [, unsigned mode] )

Відкриває файл для читання або запису. UNIX-подібна форма відкриття (створення) файлу. В випадку успішного відкриття файлу, на ASCIIZ-рядок специфікації якого вказує pathname, повертає префікс файлу; в протилежному випадку повертає (-1) і задає в зовнішню змінну errno код помилки. Ціле число access визначає права доступу, що запрошуються при відкритті файлу. Вони задаються об’єднанням операції АБО (ЧИ) символьних констант, опис яких міститься в файлі <fcntl.h> (Табл. 8).

#include <io.h>
int _open( const char *filename, int oflags )

Функція орієнтована на MS-DOS. Відкриває файл для читання або запису. В випадку успішного відкриття файлу, на ASCIIZ-рядок специфікації якого вказує filename, повертає префікс файлу; в противному випадку повертає (-1) і задає в зовнішню змінну errno код помилки. Значення oflags формується об’єднанням по АБО (ЧИ) символьних констант, описаних в файлі <fcntl.h> (Табл. 8). Прапори, що не підтримуються MS-DOS, ігноруються.

Табл. 8. Константи прав доступу і режимів створення файлів

Константа

Функція

O_RDONLY

Файл відкривається тільки для читання. Спроба запису в файл викликає повернення помилки запису. Якщо файл заданої специфікації не існує, повертається помилка при відкритті файлу

O_WRONLY

Файл відкривається тільки для запису. Спроба читання з такого файлу викликає повернення помилки функцією читання. Так може відкриватися тільки файл, не позначений при створенні як “тільки для читання”. Якщо файл з так заданою специфікацією не існує, новий файл створюється тільки в тому випадку, коли заданий прапор створення файлу, у протилежному випадку повертається помилка при відкритті файлу

O_RDWR

Файл відкривається для запису і читання. Так може відкриватися тільки існуючий файл, не позначений при створенні як “тільки для читання”. Якщо файл не існує і вказано створення файлу, він буде створений; в протилежному випадку повертається помилка при відкритті файлу

O_CREAT

Прапор створення файлу. Якщо файл зі специфікацією pathname не існує, він буде створений в заданій специфікацією директорії заданого накопичувача. При створенні файлу буде використаний третій аргумент функції - mode. Він формується об’єднанням наступних символічних констант, опис яких міститься в файлі <sys\stat.h>:

S_IFMT - маска типу файлу. Задається обов’язково, якщо встановлюється тип файлу. MS-DOS не підтримується;

S_IFDIR - файл є директорією; Turbo С створює звичайний файл з бітом “тільки для читання” байта атрибута файлу, а не директорій;

S_IFIFO - FIFO-спеціальний файл. MS-DOS не підтримує.

S_IFCHR – спеціальний символьний файл;

S_IFBLK – блоковий спеціальний файл. MS-DOS не підтримується;

S_IFREG - регулярний файл (за замовчанням);

S_IREAD - володар має право читати файл. В MS-DOS відповідає створенню файлу з бітом “тільки для читання” байта атрибуту.

S_IWRITE - володар має право записувати в файл. В MS-DOS створюється звичайний файл з архівним бітом байта атрибуту елементу директорії;

S_IEXEC - володар має право запускати файл на виконання MS-DOS не підтримується.

O_TRUNC

Файл відкривається з відсіканням попереднього вмісту.

O_EXCL

Файл відкривається в режимі виняткового доступу: спроби інших процесів (ОС UNIX) або інших комп’ютерів мережі, якщо завантажені спец. програми мережевої підтримки (MS-DOS), будуть завершуватися помилкою відкриття файлу.

O_APPEND

Покажчик запису-читання файлу встановлюється на кінець файлу.

O_ТЕХТ

Файл відкривається в текстовому режимі

O_BINARY

Файл відкривається в бінарному режимі.

O_NOINHERIT

Нащадок не успадковує файл

Табл. 9. Режими створення файлів

Константа

Функція

FA_RDONLY

Створюється файл з атрибутом “тільки для читання”

FA_HIDDEN

Створюється файл з атрибутом “що приховуються”

FA_SYSTEM

Створюється файл з атрибутом “системний”

FA_LABEL

Посилання на мітку тому. Елемент директорії буде відповідати мітці тому. Мітка тому записується тільки в кореневу директорії

FA_DIREC

Створений файл є директорією; фактично створюється звичайний файл з атрибутом “тільки для читання”

FA_ARCH

Створюється файл з атрибутом “архівний”

Окрім перерахованих функцій, файл відкривається і при його створенні. Turbo С підтримує наступні функції для створення файлів: creat(), _creat(), creatnew() і creattemp(). Далі наведені специфікації цих функцій.

#include <io.h>
int _creat( const char *path, int attrib )
int creat( const char *path, int amode )

Створюють новий файл або перезаписують існуючий; creat() є UNIX-подібною формою функції, _creat() – орієнтована на MS-DOS форма функції. В випадку успішного створення і відкриття файлу, на ASCIIZ-рядок специфікації якого вказує pathname, повертає префікс файлу; в протилежному випадку повертає (-1) і задає в зовнішню змінну егrno код помилки. Значення attrib формується об’єднанням по АБО символічних констант, описаних в файлі <dos.h>, і визначає, які біти будуть встановлені в байті атрибуту елементу директорії, який створюється функцією (Табл. 9).

Значення amode в функції creat() формується об’єднанням по АБО символічних констант, опис яких міститься в файлі <stat.h> (Табл. 8): S_IFMT, S_IFDIR. S_IFIFO, S_IFCHR, S_IFBLK, S_IFREG, S_IREAD, S_IWRITE і S_IEXEC.

#include <io.h>
int creatnew( const char *path, int attrib )

Ідентична функції _creat(), але на відміну від неї повертає помилку, якщо файл вже існує. В випадку успіху повертає префікс файлу; в протилежному випадку повертає (-1) і записує код помилки в зовнішню змінну errno . Параметр attrib задає байт атрибуту файлу і формується операцією порозрядного АБО символічних констант.(Табл. 9). Значення attrib=0 призводить до створення нормального архівного файлу. Функція вимагає версії MS-DOS 3.0 і старших.

#include <io.h>
int creattemp( char *path, int attrib )

Генерує унікальне ім’я файлу і створює файл з таким ім’ям в директорії, що задається рядком, на яку вказує path. Рядок повинен завершуватися символом ‘\’. Новий файл створюється з байтом атрибуту, що задається параметром attrib. Він формується операцією порозрядного АБО символьних констант (Табл. 9). Ім’я файлу копіюється в буфер path, так що належить зарезервувати достатньо місця для специфікації файлу. У випадку успіху повертає префікс файлу; а в протилежному випадку повертає (-1) і записує код помилки в зовнішню змінну errno. Після завершення програми не відбувається автоматичного знищення створеного файлу. Функція вимагає версії MS-DOS 3.0 і старших.

Закриття файлів, відкритих для префіксного доступу, виконується явно функціями close() і _close(). Неявне закриття файлів, відкритих програмою, виконує ОС при завершенні програми. При цьому відбувається флешування внутрішніх буферів MS-DOS відкритих файлів. Рекомендується практикою явне закриття файлів, що економить внутрішню системну пам’ять MS-DOS. Далі приводиться специфікація функцій закриття файлів:

#include <io.h>
int _close( int handle )
int close( int handle )

Закривають файл, відкритий для префіксного доступу. Параметр handle префікс файлу, повернений будь-якою з функцій префіксного створення (відкриття) файлу. В випадку успіху функції вертають 0, в протилежному випадку вертають (-1) і в зовнішню змінну errno записують код помилки.

Наведемо приклади використання розглянутих функцій. Наступна програма відкриває файл для префіксного доступу і записує туди тестовий рядок string; специфікація файлу задається першим аргументом командного рядку при запуску програми:

/* L3_12.C */
#include <stdio.h>
#include <fcntl.h>
#include <stat.h>
#include <io.h>
char string[ ] = “Тестовий рядок для запису в файл”;
main( int argc, char **argv ) {
   int handle;
   if( argc < 2 ) {
      printf( “\а Використання програми: %s ИМ’Я_ФАЙЛУ \n”, argv[0] );
      return( 1 );
   }
   if( ( handle = open( argv[1],
       O_TRUNC | O_CREAT | O_WRONLY | O_TEXT, S_IWRITE ) )== -1 ) {
      printf( “Помилка відкриття файлу %s \n ”, argv[ 1 ] );
      perror( “Причина помилки:”);
      return( 2 );
   }
   write( handle, string, sizeof( string ) );
   close( handle );
   return( 0 );
}

Ця програма відкриває файл для запису і поміщує туди всі символи з масиву string. Файл відкривається в текстовому режимі. У тому випадку, якщо файл із заданою специфікацією буде відсутній, буде створений і відкритий для запису новий файл. Якщо файл існує, його попередній вміст буде зруйновано, бо задано прапор O_TRUNC. Без цього прапору будуть переписуватися тільки перші 33 байти.

Наведена далі програма ілюструє використання MS-DOS орієнтованої форми створення файлу. Для прикладу створюється файл з бітами “архівний”, “що приховується” і “системний” байта атрибуту. Після створення файлу із заданою у командному рядку специфікацією туди записується тестовий рядок. Після цього вміст блоку в 512 байт файлу виводиться на стандартний пристрій виведення. Слід використовувати з обережністю атрибути “що приховується” та “системний”, бо такі файли не показуються в списку файлів директорія, одержаного командою dir і не можуть бути усунені командою del до тих пір, доки не буде подавлений байт “що приховується”.

Програма L3_13.C створює та відкриває файл для префіксного доступу. Специфікація файлу, що відкривається задається першим аргументом командного рядка при запуску програми:

/*L3_13. C*/
#include <sfdio.h>
#include <stat.h>
#include <io.h>
#include <dos.h>
char string[512] = “Тестовий рядок для запису в файл”;
main( argc, char**argv ) {
   int handle;
   if( argc < 2 ) {
      puts( “Використання програми. L3_13 ИМ’Я_ФАЙЛУ” );
      return( 1 );
   }
   if( ( handle = _creat( argv[ 1 ],
         FA_ARCH | FA_SYSTEM | FA_HIDDEN)) == -1 ) {
      printf( “Помилка відкриття файлу. %s \n ", argv[ 1 ] );
      perror( “Причина помилки: “ );
      return( 2 );
   }
   write( handle, string, sizeoff( string ) );
   read( handle, string, 512);
   write( 1, string, 512 );
   close( handle );
   return( 0 );
}

Приведена далі програма ілюструє використання UNIX-подібної форми створення файлу:

/*L3_14. C*/
#include<stdio.h>
#include<sfat.h>
#include <io.h>
char string [512]="Тестовий рядок для запису у файл";
main( int argc, char** argv ) {
   int handle;
   if( argc < 2 ) {
      puts( “Використання програми: L3_14 ИМЯ_ФАЙЛУ “ );
      return( 1 );
   }
   if( ( handle = creat( argv[ 1 ], S_IWRITE ) ) = -1 ) {
      printf( “Помилка відкриття файлу %s \n ”, argv[ 1 ] );
      perror( “Причина помилки: “ );
     return( 0 );
   }
   write( handle, string, sizeof( string ) );
   read( handle, string, 512 );
   write( 1, string, 512 );
   close( handle );
   return( 0 );
}

Так як в MS-DOS відсутнє право доступу “тільки запис”, створення файлу з правами S_IWRITE дозволяє і читання файлу. Але функція creat() зазнає невдачі, якщо створюваний файл вже існує і має атрибут “тільки для читання”, “системний” або “що приховується”.