Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

4.4.3. Чтение и запись

Ввод/вывод осуществляется системными вызовами

read
и
write
соответственно:

#include <sys/types.h> /* POSIX */

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

Каждая функция сделана как можно проще. Аргументами являются дескриптор открытого файла, указатель на буфер для чтения или записи данных и число читаемых или записываемых байтов.

Возвращаемое значение является числом действительно прочитанных или записанных байтов. (Это число может быть меньше запрошенного: при операции чтения это происходит, когда в файле осталось меньше

count
байтов, а при операции записи это случается, когда диск заполнен или произошла еще какая-нибудь ошибка.) Возвращаемое значение -1 означает возникшую ошибку, в этом случае errno указывает эту ошибку. Когда
read
возвращает 0, это означает, что достигнут конец файла.

Теперь мы можем показать оставшуюся часть кода для

ch04-cat
. Процедура
process
использует 0 для стандартного ввода, если именем файла является «
–
» (строки 50 и 51). В противном случае она открывает данный файл:

36 /*

37 * process --- сделать что-то с файлом, в данном случае,

38 * послать его в stdout (fd 1).

39 * Возвращает 0, если все нормально; в противном случае 1.

40 */

41

42 int

43 process(char *file)

44 {

45 int fd;

46 ssize_t rcount, wcount;

47 char buffer[BUFSIZ];

48 int errors = 0;

49

50 if (strcmp(file, "-") == 0)

51 fd = 0;

52 else if ((fd = open(file, O_RDONLY)) < 0) {

53 fprintf(stderr, "%s: %s: cannot open for reading: %s\n",

54 myname, file, strerror(errno));

55 return 1;

56 }

Буфер

buffer
(строка 47) имеет размер
BUFSIZ
; эта константа определена В
<stdio.h>
как «оптимальный» размер блока для ввода/вывода. Хотя значение
BUFSIZ
различается в разных системах, код, использующий эту константу, чистый и переносимый.

Основой процедуры является следующий цикл, который повторно читает данные до тех пор, пока не будет достигнут конец файла или не возникнет ошибка.

58 while ((rcount = read(fd, buffer, sizeof buffer)) > 0) {

59 wcount = write(1, buffer, rcount);

60 if (wcount != rcount) {

61 fprintf(stderr, "%s: %s: write error: %s\n",

62 myname, file, strerror(errno));

63 errors++;

64 break;

65 }

66 }

Переменные

rcount
и
wcount
(строка 45) имеют тип
ssize_t
, «знаковый
size_t
», который позволяет хранить в них отрицательные значения. Обратите внимание, что число байтов, переданное
write
, является значением, возвращенным
read
(строка 59). Хотя мы хотим читать порциями фиксированного размера в
BUFSIZ
, маловероятно, что размер самого файла кратен
BUFSIZ
. При чтении из файла завершающей, меньшей порции байтов, возвращаемое значение указывает, сколько байтов buffer получили новые данные. В стандартный вывод должны быть скопированы только эти байты, а не весь буфер целиком.

Условие '

wcount != rcount
' в строке 60 является правильным способом проверки на ошибки; если были записаны некоторые, но не все данные,
wcount
будет больше нуля, но меньше
rcount
.

В заключение

process
проверяет наличие ошибок чтения (строки 68–72), а затем пытается закрыть файл. В случае (маловероятном) неудачного завершения
close
(строка 75) она выводит сообщение об ошибке. Избежание закрытия стандартного ввода не является абсолютно необходимым в данной программе, но является хорошей привычкой при разработке больших программ, в случае, когда другой код где-то в другом месте хочет что-то с ним делать или если порожденная программа будет наследовать его. Последний оператор (строка 82) возвращает 1, если были ошибки, и 0 в противном случае.

  • Читать дальше
  • 1
  • ...
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: