Pergunta

Eu estou fazendo um pequeno projeto em C depois de muito tempo longe dele. Estes acontecem para incluir alguns manipulação de arquivos. Eu observei em vários documentos que existem funções que retornam alças FILE * e outros que retornam (pequeno inteiro) descritores. Ambos os conjuntos de funções de oferecer os mesmos serviços básicos que eu preciso para que ele realmente não importa que eu uso.

Mas estou curioso sobre a sabedoria coleção: é melhor usar fopen() e amigos, ou open() e amigos

Editar Desde Alguém mencionou tamponada vs dispositivos sem buffer e acessar, devo acrescentar que uma parte deste pequeno projeto vai escrever um driver userspace arquivos no FUSE. Assim, o nível de acesso de arquivo poderia facilmente estar em um dispositivo (por exemplo, um CD-ROM ou uma unidade SCSI) como em um "arquivo" (ou seja, uma imagem).

Foi útil?

Solução

A objeção de que "fopen" é portátil e "aberto" não é é falso.

fopen faz parte do libc, aberto é uma chamada de sistema POSIX.

Cada um é tão portátil como o lugar de onde vêm.

E / S para arquivos fopen'ed é (você deve assumir que seja, e para efeitos práticos, é) tamponada por libc, arquivo descritores open () 'ed não são tamponados por libc (que pode muito bem ser, e normalmente são colocados no sistema de arquivos -., mas não tudo o que abrir () é um arquivo em um sistema de arquivos

O que é o ponto de fopen'ing, por exemplo, um nó de dispositivo como / dev / sg0, digamos, ou / dev / tty0 ... O que você vai fazer? Você vai fazer um ioctl em um arquivo *? Boa sorte com isso.

Talvez você deseja abrir com algumas bandeiras como O_DIRECT - não faz sentido com fopen ()

.

Outras dicas

É melhor usar open () se você está aderindo a sistemas Unix-like e que você pode gostar:

  • ter mais controle de grão fino sobre bits de permissão unix na criação do arquivo.
  • Use as funções de nível mais baixo, tais como leitura / escrita / mmap em oposição à C tamponada de fluxo de I / O funções.
  • Use descritor de arquivo (fd) agendamento com base IO (pesquisa, selecionar, etc.) Você pode obter de curso de um fd de um FILE * usando fileno (), mas é preciso ter cuidado para não misturar FILE * funções de fluxo com base com fd funções baseadas.
  • Abra qualquer dispositivo especial (não um arquivo regular)

É melhor usar fopen / fread / fwrite para máxima portabilidade, uma vez que estas são funções C padrão, as funções que eu mencionei acima não são.

obras fopen a um nível mais elevado do que aberto .... fopen Retorna um ponteiro para fluxo de arquivo que é semelhante ao fluxo de abstração que você lê em C ++

abertas Retorna um descritor de arquivo para o arquivo aberto ... Ele não fornece uma abstração fluxo e você é responsável por manipular os bits e bytes-se ... Esta é a um nível inferior em comparação com fopen

streams stdio são tamponados, enquanto Open () descritores de arquivos não são. Depende do que você precisa. Você também pode criar um do outro:

fileno int (FILE * stream) retorna o descritor de arquivo para um arquivo *, FILE * fdopen (fildes int, char const * mode) cria um arquivo * de um descritor de arquivo.

Tenha cuidado ao misturar-tamponada e não tamponada IO, já que você vai perder o que está em seu buffer quando você não nivelá-lo com fflush ().

Sim. Quando você precisar de uma alça de baixo nível.

sistemas operacionais em Unix, você pode geralmente identificadores de arquivo de troca e tomadas.

Além disso, alças de baixo nível para fazer uma melhor compatibilidade ABI do que os ponteiros de arquivo.

Normalmente, você deve favorecer usando a biblioteca padrão (fopen). No entanto, há ocasiões em que você vai precisar usar aberto diretamente.

Um exemplo que vem à mente é a de trabalho em torno de um bug em uma versão mais antiga do Solaris que fez fopen falhar após 256 arquivos estavam abertos. Isso porque eles erroniously utilizado um unsigned char para o campo fd na sua implementação struct arquivo em vez de um int. Mas este era um caso muito específico.

read () e write () usar sem buffer I / O. ( fd : integer descritor de arquivo)

fread () e fwrite () uso tamponada I / O. ( arquivo * ponteiro estrutura)

Os dados binários gravados em um tubo com write () não pode ser capaz de ler dados binários com fread () , por causa de alinhamentos byte, tamanhos variáveis, etc. É uma porcaria-shoot.

A maioria dos dispositivos de baixo nível usa o código do driver sem buffer de E / S chamadas.

A maioria dos usos nível de aplicação de E / S em buffer.

Utilize o arquivo * e suas funções associadas é OK em uma base de máquina-a-máquina, mas a portabilidade está perdido em outras arquiteturas na leitura e escrita de dados binários. fwrite () é tamponada de I / O e podem conduzir a resultados incertos se escrito para uma arquitetura de 64 bits e de execução em um 32 bits; ou (Windows / Linux). A maioria OSs têm macros de compatibilidade dentro de seu próprio código para evitar isso.

Para binários de baixo nível I / O portabilidade read () e write () garantia o mesmo binário lê e escreve quando compilado em arquiteturas diferentes. A coisa básica é escolher uma forma ou de outra e ser consistente sobre isso, todo o conjunto de binário.

<stdio.h>  // mostly FILE*  some fd input/output parameters for compatibility
             // gives you a lot of helper functions -->
List of Functions
       Function      Description
       ───────────────────────────────────────────────────────────────────
       clearerr      check and reset stream status
       fclose        close a stream
       fdopen        stream open functions //( fd argument, returns FILE*)                      feof          check and reset stream status
       ferror        check and reset stream status
       fflush        flush a stream
       fgetc         get next character or word from input stream
       fgetpos       reposition a stream
       fgets         get a line from a stream
       fileno        get file descriptor   // (FILE* argument, returns fd) 
       fopen         stream open functions
       fprintf       formatted output conversion
       fpurge        flush a stream
       fputc         output a character or word to a stream
       fputs         output a line to a stream
       fread         binary stream input/output
       freopen       stream open functions
       fscanf        input format conversion
       fseek         reposition a stream
       fsetpos       reposition a stream
       ftell         reposition a stream
       fwrite        binary stream input/output
       getc          get next character or word from input stream
       getchar       get next character or word from input stream
       gets          get a line from a stream
       getw          get next character or word from input stream
       mktemp        make temporary filename (unique)
       perror        system error messages
       printf        formatted output conversion
       putc          output a character or word to a stream
       putchar       output a character or word to a stream
       puts          output a line to a stream
       putw          output a character or word to a stream
       remove        remove directory entry
       rewind        reposition a stream
       scanf         input format conversion
       setbuf        stream buffering operations
       setbuffer     stream buffering operations
       setlinebuf    stream buffering operations
       setvbuf       stream buffering operations
       sprintf       formatted output conversion
       sscanf        input format conversion
       strerror      system error messages
       sys_errlist   system error messages
       sys_nerr      system error messages
       tempnam       temporary file routines
       tmpfile       temporary file routines
       tmpnam        temporary file routines
       ungetc        un-get character from input stream
       vfprintf      formatted output conversion
       vfscanf       input format conversion
       vprintf       formatted output conversion
       vscanf        input format conversion
       vsprintf      formatted output conversion
       vsscanf       input format conversion

Assim, para uso básico Eu pessoalmente usar o acima sem misturar expressões idiomáticas muito.

Por outro lado,

<unistd.h>   write()
             lseek()
             close()
             pipe()
<sys/types.h>
<sys/stat.h>
<fcntl.h>  open()
           creat()
           fcntl() 
all use file descriptors.

Estes fornecem controle de grão fino sobre leitura e escrita bytes (Recomendado para dispositivos especiais e fifos (tubos)).

Então, novamente, usar o que você precisa, mas manter consistente em seus idiomas e interfaces. Se a maior parte de sua base de código usa um modo, o uso que também, a menos que haja uma verdadeira razão para não. Ambos os conjuntos de funções de I / O de biblioteca são extremamente confiáveis e usado milhões de vezes por dia.

Nota - Se você está interface C / S com outro idioma, (Perl, Python, Java, C #, lua ...) confira o que os desenvolvedores desses idiomas recomendo antes de escrever o código C e poupar algum problema.

fopen e seus primos são tamponados. aberto, ler e escrever não são tamponados. Sua aplicação pode ou não se importa.

fprintf e scanf Tem uma API mais rico que lhe permite ler e escrever arquivos de texto formatado. ler e escrever usar matrizes fundamentais de bytes. Conversões e formatação devem ser feitas à mão.

A diferença entre descritores de arquivo e (FILE *) é realmente irrelevante.

Randy

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top