Int open (const char *имя_файла, int доступ);
Данная функция открывает файл для записи/чтения и возвращает дескриптор файла, который можно присвоить целой переменной и использовать ее для ссылки на файл. Функция в случае успеха возвращает дескриптор файла или «-1» при ошибке.
Аргумент доступ задает тип допустимых операций для файла и может принимать одно из находящихся в файле «fcntl.h» константных значений:
O_APPEND - файл открывается для добавления в конец
O_BINARY - файл открывается для добавления в конец в двоичном режиме
O_CREAT - создается и открывается новый файл
O_RDONLY - создается и открывается новый файл только для чтения
O_RDWR - создается и открывается новый файл для чтения и записи
O_TEXT - создается и открывается новый файл в текстовом режиме
O_TRUNC - открывается существующий файл, а его содержимое удаляется
O_WRONLY - открывается только для записи существующий файл, а его содержимое удаляется
ПРИМЕЧАНИЕ
|
Если нужно задать более одной константы, то они связываются последовательно с помощью символа «|». |
Пример:
int handle;
handle=open (“file.bat”,O_CREAT | O_WRONLY);
13.6.2. Закрытие файла |
Закрытие ранее открытого файла производится с помощью функции close().
Формат:
int close (int handle);
Данная функция в случае успеха возвращает ноль и «-1» - при ошибке.
Пример:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
main ()
{
int handle;
. . .
if ((handle=open (“file”, O_RDONLY)==-1)
fprintf (stderr, “Невозможно открыть файл!”);
. . .
close (handle);
}
13.7. Переопределение файлов и потоков |
С началом выполнения любой программы автоматически открываются пять файлов (потоков), с которыми связаны дескрипторы.
Таблица 2
Дескриптор |
Поток (файл) |
0 |
stdin |
1 |
stdout |
2 |
stderr |
3 |
stdaux |
4 |
stdprn |
С помощью этих дескрипторов программа может иметь доступ к стандартным файлам. Можно определить и дескрипторы, связанные с любымпотоком, с помощью функции fileno() из библиотеки «stdio.h».
Формат:
int fileno (FILE *имя_указателя);
Данная функция возвращает дескриптор файла, на который ссылается указатель *имя_указателя.
Если поток имеет несколько дескрипторов, то возвращается тот, который связывается с потоком при первичном открытии файла. Одному и тому же файлу можно назначить несколько дескрипторов с помощью функций dup() и dup2(). Обычно они используются для переадресации обмена со стандартными файлами ввода-вывода.
Формат:
int dup (int дескриптор);
Данная функция назначает новый дескриптор файлу с дескриптором дескриптор. В случае успеха функция возвращает новый дескриптор, а при ошибке – «-1».
НЕ РЕКОМЕНДУЕТСЯ
|
Не пытайтесь перенаправить поток stderr. Не используйте поток stderr для каких либо других целей, кроме вывода предупреждений и сообщений об ошибках. |
Во внутренней таблице открытых файлов системы отыскивается новый свободный элемент, в который копируется элемент внутренней таблицы с порядковым номером дескриптор. В результате в таблице появится два элемента, которые ссылаются на один и тот же файл.
Пример: назначение нового дескриптора потоку
#include <stdio.h>
#include <io.h>
int newhandle (FILE *fp)
{
int new;
if ((new=dup (fileno (fp)))==-1)
printf (“нельзя назначить новый дескриптор потоку\n”);
return new;
}
main ()
{
FILE *fptr;
int newhndl;
. . .
newhndl=newhandle(fptr)
}
Формат:
int dup2 (int стар_дескриптор, int нов_дескриптор);
Данная функция копирует информацию о файле с дескриптором стар_дескриптор в строку таблицы файлов с номером нов_дескриптор. Если эта строка таблицы была отведена под другой файл или устройство, то они закрываются. В случае успеха функция возвращает ноль, а приошибке – «-1».
ПРИМЕЧАНИЕ
|
Помните, что перенаправление потоков stdin и stdout – это возможность операционной системы, а не самого языка Си. Тем не менее, это еще одно свидетельство гибкости и удобства потоков ввода-вывода. Более подробную информацию о перенаправлении можно найти в документации операционной системы. |
Пример:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
main ()
{
int e;
e=open (“file.out”, O_CREAT | O_WRONLY);
dup2 (e, 1); // переназначит стандартный вывод с дескриптором 1 (stdin) в «file.out»
printf (“Пример\n”);
}
Результат: слово “Пример” в файле «file.out» без вывода на экран
13.8. функции чтения и записи данных |
К функциям чтения и записи данных относятся две функции read() и write() из библиотеки «io.h».
Формат:
int read (int дескриптор, void *имя_указателя, unsigned колич);
Данная функция выполняет чтение колич-байт из открытого файла с дескриптором дескриптор и размещенного по адресу, на который ссылается указатель *имя_указателя. В случае успеха функция возвращает прочитанное число байтов, а при ошибке – «-1».
Формат:
int write (int дескриптор, void *имя_указателя, unsigned колич);
Данная функция выполняет запись колич-байт в открытый файл с дескриптором дескриптор и размещенного по адресу, на который ссылается указатель *имя_указателя. В случае успеха функция возвращает записанное число байтов, а при ошибке – «-1».
Функция lseek() позволяет установить текущий указатель чтения/записи. Функция tell() позволяет определить текущую позицию указателя.
ВНИМАНИЕ
|
Функции lseek() и tell() нельзя применять к устройствам. |
Пример:
char string[512]=”Тестовая строка”;
. . .
handle=creat (“DATA”, S_IREAD | S_IWRITE); // S_IREAD и S_IWRITE находятся в «sys\stat.h»
write (handle, string, sizeof (string));
read (handle, string, 512);
. . .
close (handle);
13.9. Ввод-вывод для консоли и портов |
С помощью функций, прототипы которых находятся в библиотеке «stdio.h», нельзя выполнить неотображенный на экран ввод символов,определить нажатие специальной клавиши и т.д. Для выполнения таких действий используются функции ввода-вывода для консоли ипортов, прототипы которых находятся в библиотеке «conio.h».
Функции для работы с консолью:
cgets () – вводит строку с консоли
cputs () – выводит строку в консоль
cscanf () – вводит форматированные данные с консоли
cprintf () – выводит форматированные данные в консоль
getch () – вводит символ с консоль
getc () – выводит символ с консоли и отображает его на экране
ungetch () – «возвращает» прочитанный символ на консоль (записывает непосредственно в буфер клавиатуры символ, который будет прочитан при выполнении следующей операции чтения)
putch () – выводит символ на консоль
kbhit () – проверяет, была ли нажата клавиша на клавиатуре
Функции для работы с портами:
inp () – читает один байт из порта
inpw () – читает два байта из порта
outp () – записывает один байт в порт
outpw () – записывает два байта в порт
ВНИМАНИЕ
|
Для консоли и порта нет функций открывающих или закрывающих, т.к. консоль и порты не закрываются и не открываются во время ввода-вывода. |
Для организации интерфейса с пользователем, при котором нажатие клавиши вызывает мгновенную реакцию программы без отображения введенного символа на экране, полезна функция getch().
Формат:
int getch (void);
Данная функция выполняет ввод с клавиатуры одного символа и не выполняет эхо ввода на экран. В случае успеха функция возвращаетвведенный символ.
ПРИМЕЧАНИЕ
|
Для чтения функциональных клавиш функция должна вызываться дважды; в этом случае первый вызов возвращает ноль, а второй – код нажатой клавиши. |
Пример:
#include <stdio.h>
#include <conio.h>
main ()
{
int ch;
do
{
puts (“Нажмите клавишу\n”);
if (!(ch=getch()))
{
ch=getch();
printf (“Специальная клавиша (Код %u)\n”, ch);
}
else printf (“Символьная клавиша %c (Код %u)\n”, ch, ch);
puts (“Продолжить? (y/n)”);
}
while ((ch=getch())==’y’ || ch==’n’);
return 0;
}
Результат:
Нажмите клавишу
// нажат 0
Символьная клавиша 0 (Код 48)
Продолжить? (y/n)
Нажмите клавишу
// нажат F1
Символьная клавиша (Код 59)
Продолжить? (y/n)