Чтение отчетов Bad File Descriptor, несмотря на то, что getc успешно использует тот же fd для чтения char

У меня есть этот код C:

FILE * fd = fopen(filename,"rb");
printf("%c ",(char)getc(fd)); // returns expected char
unsigned char buffer[10];
printf("%d ",read(fd, &buffer, 10)); // -1
printf("%d\n",errno); // 9

getc возвращает char из входного файла, как и ожидалось. Однако read возвращает ошибку (-1), а errno имеет значение 9 (неверный файловый дескриптор). Очевидно, что с дескриптором файла все в порядке, так как getc удается использовать его для чтения символа.

В чем проблема?


person user6243824    schedule 23.04.2016    source источник
comment
Разве компилятор не выкрикивает вам предупреждение? Отнеситесь серьезно к предупреждениям!   -  person alk    schedule 23.04.2016


Ответы (3)


fopen и read являются функциями разных семейств. Семьи:

  • fopen с fread (а также getc) из стандартной библиотеки C.

  • open с read из спецификации POSIX.

Первое семейство использует файловые указатели как FILE* типы, а второе использует файловые дескрипторы как int типы. Вы не можете смешивать эти два семейства до тех пор, пока вы не конвертируете один тип файлового дескриптора в другой. Преобразование из FILE* в int выполняется с помощью функции POSIX fileno.

В вашем случае используйте fread для чтения из файла.

person atturri    schedule 23.04.2016

Вместо read(fd, &buffer, 10)
вы хотите использовать: fread(buffer, 1, 10, fd)

FILE* — это не файловый дескриптор, это поток; вот почему вы должны использовать fread() (для которого нужен поток) вместо read() (для которого нужен файловый дескриптор). Кроме того, следует использовать buffer вместо &buffer (что приведет к UB).

person shrike    schedule 23.04.2016

Это странный код. Вы хотите напечатать код возврата чтения, а не данные, которые были прочитаны?

Сначала исправьте свое чтение, вам нужно fread вместо чтения:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *" stream );

Сбой вызван тем, что вы перезаписываете адрес буфера, а не записываете в сам буфер.

Таким образом, printf("%d ",read(fd, &buffer, 10)); вместо этого должно быть printf("%d ",fread(buffer, 1, 10, fd));, чтобы считать 10 (nmemb=10) байт (size=1) в буфер.

person Henno Brandsma    schedule 23.04.2016
comment
FILE*, возвращаемый функцией fopen(), не является файловым дескриптором; read() нужен файловый дескриптор; Вместо этого следует использовать fread(). — шрайк, только что отредактировал - person shrike; 23.04.2016