Системное программирование Линукс. Linux. Системное программирование. Вступление
Скачать 0.65 Mb.
|
104 Режимы. Аргумент mode описывает, как открывать конкретный файл. Данный аргумент может быть представлен одной из следующих строк. r — файл открывается для чтения. Поток данных устанавливается в начале файла. r+ — файл открывается как для чтения, так и для записи. Поток данных уста навливается в начале файла. w — файл открывается для записи. Если файл существует, то он усекается до нулевой длины. Если файл не существует, он создается. Поток данных устанав ливается в начале файла. w+ — файл открывается для чтения и для записи. Если файл существует, то он усекается до нулевой длины. Если файл не существует, он создается. Поток данных устанавливается в начале файла. a — файл открывается для дополнения в режиме дозаписи. Если файл не суще ствует, то он создается. Поток данных устанавливается в конце файла. Все вводимые данные дозаписываются в файл. a+ — файл открывается для дополнения и считывания в режиме дозаписи. Если файл не существует, то он создается. Поток данных устанавливается в конце файла. Все вводимые данные дозаписываются в файл. ПРИМЕЧАНИЕ В указанном режиме также может содержаться символ b, хотя в Linux это значение всегда игнорирует- ся. Некоторые операционные системы по-разному обрабатывают текст и двоичные файлы. Сим- вол b означает, что файл должен быть открыт именно в двоичном режиме. Linux, как и все операцион- ные системы, соответствующие стандарту POSIX, воспринимает текст и двоичные файлы одинаково. В случае успеха функция fopen() возвращает допустимый указатель FILE . При ошибке она возвращает NULL и устанавливает errno соответствующее значение. Например, следующий код открывает для чтения файл /etc/manifest и ассоци ирует его с потоком данных stream : FILE *stream; stream = fopen ("/etc/manifest", "r"); if (!stream) /* ошибка */ Открытие потока данных с помощью файлового дескриптора Функция fdopen() преобразует уже открытый файловый дескриптор ( fd ) в поток данных: #include FILE * fdopen (int fd, const char *mode); Глава 3. Буферизованный ввод-вывод 105 Могут использоваться те же режимы, что и с функцией fopen() , при этом они должны быть совместимы с режимами, которые изначально применялись для от крытия файлового дескриптора. Режимы w и w+ можно указывать, но они не будут приводить к усечению файла. Поток данных устанавливается в файловую позицию, которая соответствует данному файловому дескриптору. После преобразования файлового дескриптора в поток данных вводвывод больше не выполняется напрямую с этим файловым дескриптором. Тем не менее это не возбраняется. Обратите внимание: файловый дескриптор не дублируется, а просто ассоциируется с новым потоком данных. При закрытии потока данных закроется и файловый дескриптор. В случае успеха fdopen() возвращает допустимый указатель файла, при ошибке она возвращает NULL и присваивает errno соответствующее значение. Например, следующий код открывает файл /home/kidd/map.txt с помощью сис темного вызова open() , а потом создает ассоциированный поток данных, опираясь на базовый файловый дескриптор: FILE *stream; int fd; fd = open ("/home/kidd/map.txt", O_RDONLY); if (fd == -1) /* ошибка */ stream = fdopen (fd, "r"); if(!stream) /* ошибка */ Закрытие потоков данных Функция fclose() закрывает конкретный поток данных: #include int fclose(FILE*stream); Сначала сбрасываются на диск все буферизованные, но еще не записанные данные. В случае успеха fclose() возвращает 0 . При ошибке она возвращает EOF (конец файла) и устанавливает errno в соответствующее значение. Закрытие всех потоков данных. Функция fcloseall() закрывает все потоки данных, ассоциированные с конкретным процессом, в частности используемые для стандартного ввода, стандартного вывода и стандартных ошибок: #define _GNU_SOURCE #include int fcloseall(void); Перед закрытием все потоки данных сбрасываются на диск. Функция является специфичной для Linux и всегда возвращает 0 Закрытие потоков данных 106 Считывание из потока данных Теперь, когда мы умеем открывать и закрывать потоки данных, поговорим о том, как сделать чтото полезное — как считать поток данных, а затем как записать в него информацию. Стандартная библиотека C реализует множество функций для считывания из открытого потока данных. Среди них есть как общеизвестные, так и мало распространенные. В этом разделе мы рассмотрим три наиболее популярных варианта считывания: считывание одного символа в момент времени, считыва ние целой строки в момент времени, считывание двоичных данных. Чтобы из потока данных можно было считать информацию, он должен быть открыт как поток данных ввода в подходящем режиме, то есть в любом допустимом режи ме, кроме w и a Считывание одного символа в момент времени Зачастую идеальный принцип вводавывода сводится к считыванию одного сим вола в момент времени. Функция fgetc() используется для считывания отдельно го символа из потока данных: #include int fgetc(FILE*stream); Эта функция считывает следующий символ из stream и возвращает его как unsigned char , приведенный к int . Такое приведение осуществляется, чтобы получить достаточно широкий диапазон для уведомлений EOF или описания ошибок: в та ких случаях возвращается EOF . Возвращаемое значение fgetc() должно быть сохра нено в int . Сохранение в char — распространенный и опасный промах, ведь в таком случае вы не можете обнаруживать ошибки. В следующем коде мы считываем отдельно взятый символ из stream , проверяем наличие ошибок и выводим результат как char : int c; c = fgetc (stream); if (c == EOF) /* ошибка */ else printf ("c=%c\n", (char) c); Поток данных, указанный в stream , должен быть открыт для чтения. Возврат символа в поток данных. В рамках стандартного вводавывода предо ставляется функция для перемещения символа обратно в поток данных. С ее по мощью вы можете «заглянуть» в поток данных и возвратить символ обратно, если окажется, что он вам не подходит: Глава 3. Буферизованный ввод-вывод |