Qual é a diferença entre um descritor de arquivo e um ponteiro de arquivo?

Respostas:

144

Um descritor de arquivo é um "identificador" inteiro de baixo nível usado para identificar um arquivo aberto (ou soquete, ou qualquer outro) no nível do kernel, no Linux e em outros sistemas semelhantes ao Unix.

Você passa descritores de arquivo "simples" para chamadas Unix reais, como read(), write()e assim por diante.

Um FILEponteiro é uma construção de nível de biblioteca padrão C, usada para representar um arquivo. O FILEencapsula o descritor de arquivo e adiciona buffering e outros recursos para tornar o I / O mais fácil.

Você passa FILEponteiros para funções C padrão, como fread()e fwrite().

desanuviar
fonte
@nvl: fildes certamente está disponível para Windows, por exemplo, msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm
2
@unwind O que você quis dizer com descritores de arquivo "nus"? A referência vinculada diz que o fdé o primeiro argumento para read(). Por que você chama isso de pelado?
Geek
3
@Geek Comparado ao FILE *tipo da biblioteca padrão , o descritor de arquivo inteiro é "menos empacotado", ou seja, "nu".
relaxe
57

Um está armazenado em buffer ( FILE *) e o outro não. Na prática, você deseja usar FILE *quase sempre quando estiver lendo um arquivo 'real' (ou seja, na unidade), a menos que saiba o que está fazendo ou que o arquivo seja realmente um soquete ou algo assim.

Você pode obter o descritor de arquivo FILE *usando fileno()e pode abrir um buffer FILE *de um descritor de arquivo usandofdopen()

Ben
fonte
12
+1 para apontar fileno (), a organização das páginas de manual torna este difícil de encontrar. O mesmo para fdopen ().
BD em Rivenhill
20

Um descritor de arquivo é apenas um inteiro que você obtém da open()chamada POSIX . Usando o C padrão, fopen()você obtém uma FILEestrutura de volta. A FILEestrutura contém este descritor de arquivo, entre outras coisas, como fim de arquivo e indicador de erro, posição do fluxo, etc.

Portanto, o uso fopen()oferece uma certa abstração em comparação com open(). Em geral, você deve usar, fopen()já que é mais portátil e você pode usar todas as outras funções C padrão que usam a FILEestrutura, ou seja, fprintf()e família.

Não há problemas de desempenho usando qualquer um.

Martin Wickman
fonte
8
1 para trazer portabilidade. FILE faz parte da Biblioteca C padrão (de volta a C89 / C90); descritores de arquivo, não.
tomlogic
15

Descritor de arquivo vs ponteiro de arquivo

Descritor de arquivo:

Descritor de arquivo é um valor inteiro retornado pela open()chamada do sistema.

int fd = open (filePath, mode);

  1. Manipulador de nível baixo / kernel.
  2. passe para ler () e escrever () de chamadas de sistema UNIX.
  3. Não inclui buffering e tais recursos.
  4. Menos portátil e sem eficiência.

Ponteiro de arquivo:

File Pointer é um ponteiro para uma estrutura C retornada pela fopen()função de biblioteca, que é usada para identificar um arquivo, envolver o descritor de arquivo, a funcionalidade de buffer e todas as outras funcionalidades necessárias para a operação de E / S. O ponteiro de arquivo é do tipo FILE , cuja definição pode ser encontrado em "/usr/include/stdio.h" . Esta definição pode variar de um compilador para outro.

FILE *fp = fopen (filePath, mode);

// A FILE Structure returned by fopen 
    typedef struct 
    {
        unsigned char   *_ptr;
        int     _cnt;
        unsigned char   *_base;
        unsigned char   *_bufendp;
        short   _flag;
        short   _file;
        int     __stdioid;
        char    *__newbase;
#ifdef _THREAD_SAFE
        void *_lock;
#else
        long    _unused[1];
#endif
#ifdef __64BIT__
        long    _unused1[4];
#endif /* __64BIT__ */
    } FILE;
  1. É uma interface de alto nível.
  2. Passado para as funções fread () e fwrite ().
  3. Inclui buffering, indicação de erro e detecção de EOF, etc.
  4. Oferece maior portabilidade e eficiência.
Yogeesh HT
fonte
1
Você é capaz de apoiar essa afirmação de maior eficiência? Eu nunca ouvi isso.
Gid
1
A alegação de "eficiência" pode ser devido ao buffering. Com um descritor de arquivo, cada read () ou write () é uma syscall, e cada syscall deve ser considerada cara. Com um FILE *, o armazenamento em buffer significa que algumas leituras e gravações não serão chamadas em syscall.
Mike Spear
12

Deseja adicionar pontos que podem ser úteis.

SOBRE FILE *

  1. não pode ser usado para comunicação entre processos (IPC).
  2. use-o quando precisar de E / S com buffer de propósito geral. (printf, frpintf, snprintf, scanf)
  3. Eu o uso muitas vezes para logs de depuração. exemplo,

                 FILE *fp;
                 fp = fopen("debug.txt","a");
                 fprintf(fp,"I have reached till this point");
                 fclose(fp);

SOBRE FILE DESCRIPTOR

  1. Geralmente é usado para IPC.

  2. Fornece controle de baixo nível para arquivos em sistemas * nix. (Dispositivos, arquivos, soquetes, etc), portanto, mais poderoso que o FILE *.

Akshay Patil
fonte
Você não pode usar fdopen()para fazer coisas como IPC e dispositivos com FILE*?
osvein
Na verdade, sim e não. Você não pode configurar e inicializar o IPC com FILE*, mas pode criar um a FILE*partir de um descritor de arquivo ( fdopen()) e, posteriormente, fechar o FILEirá fechar o descritor também. Portanto, você pode fazer IPC, mas terá que lidar um pouco com os descritores de arquivo para facilitar qualquer IPC direto.
Micah W
3

FILE *é mais útil quando você trabalha com arquivos de texto e entrada do usuário / saída, porque ele permite que você use funções da API, como sprintf(), sscanf(), fgets(), feof()etc.

A API do descritor de arquivo é de baixo nível, portanto, permite trabalhar com sockets, pipes, arquivos mapeados na memória (e arquivos regulares, é claro).

qrdl
fonte
1
+1 porque você adicionou arquivos mapeados na memória, visto que na minha leitura atual, as outras respostas já foram fornecidas.
ernie.cordell
3

Apenas uma nota para encerrar a discussão (se estiver interessado) ....

fopenpode ser inseguro e você provavelmente deve usar fopen_sou opencom bits exclusivos definidos. C1X está oferecendo xmodos, assim você pode fopencom os modos "rx", "wx", etc.

Se você usar open, você pode considerar open(..., O_EXCL | O_RDONLY,... )ou open(..., O_CREAT | O_EXCL | O_WRONLY,... ).

Veja, por exemplo, Não faça suposições sobre fopen () e criação de arquivo .

jww
fonte
Como fopen_snão parece estar disponível com POSIX, suponho que o soultion mais portátil seria para open(2)e então fdopen(2). (deixando as janelas de lado). Além disso, o que seria mais rápido fopen_s()ou open(2)seguido por fdopen(2)?
Mihir
1

As chamadas do sistema usam principalmente o descritor de arquivo, por exemplo reade write. A função de biblioteca usará os ponteiros de arquivo ( printf, scanf). Porém, as funções da biblioteca estão usando apenas chamadas do sistema internamente.

Pavunkumar
fonte
Não sei por que você está dizendo que as funções da biblioteca estão usando apenas chamadas de sistema internas: Se você se refere às funções CI / O padrão (ou qualquer outra), não tenho certeza se isso (universalmente?) É verdade. Caso contrário, não foi isso que você disse, então gostaria de ver a linguagem em sua postagem um pouco mais limpa. A última frase me deixa perplexo.
ernie.cordell
1

Encontrei um bom recurso aqui , dando uma visão geral de alto nível das diferenças entre os dois:

Quando você deseja fazer entrada ou saída para um arquivo, você tem a opção de dois mecanismos básicos para representar a conexão entre o seu programa e o arquivo: descritores de arquivo e fluxos. Os descritores de arquivo são representados como objetos do tipo int, enquanto os fluxos são representados como objetos FILE *.

Os descritores de arquivo fornecem uma interface primitiva de baixo nível para operações de entrada e saída. Ambos os descritores e fluxos de arquivo podem representar uma conexão com um dispositivo (como um terminal), ou um pipe ou socket para se comunicar com outro processo, bem como um arquivo normal. Mas, se você quiser fazer operações de controle específicas para um determinado tipo de dispositivo, deverá usar um descritor de arquivo; não há recursos para usar fluxos dessa maneira. Você também deve usar descritores de arquivo se o seu programa precisar fazer entrada ou saída em modos especiais, como entrada não bloqueante (ou com polling) (consulte Sinalizadores de status de arquivo).

Os fluxos fornecem uma interface de nível superior, em camadas sobre os recursos do descritor de arquivo primitivo. A interface de fluxo trata todos os tipos de arquivos da mesma forma - a única exceção sendo os três estilos de buffer que você pode escolher (consulte Buffer de fluxo).

A principal vantagem de usar a interface de fluxo é que o conjunto de funções para executar operações reais de entrada e saída (em oposição às operações de controle) em fluxos é muito mais rico e poderoso do que os recursos correspondentes para descritores de arquivo. A interface do descritor de arquivo fornece apenas funções simples para a transferência de blocos de caracteres, mas a interface de fluxo também oferece funções poderosas de entrada e saída formatadas (printf e scanf), bem como funções para entrada e saída orientadas a caracteres e linhas.

Como os fluxos são implementados em termos de descritores de arquivo, você pode extrair o descritor de arquivo de um fluxo e executar operações de baixo nível diretamente no descritor de arquivo. Você também pode abrir inicialmente uma conexão como um descritor de arquivo e, em seguida, fazer um fluxo associado a esse descritor de arquivo.

Em geral, você deve continuar usando streams em vez de descritores de arquivo, a menos que haja alguma operação específica que você deseja fazer que só possa ser feita em um descritor de arquivo. Se você for um programador iniciante e não tiver certeza de quais funções usar, sugerimos que se concentre nas funções de entrada formatada (consulte Entrada formatada) e nas funções de saída formatada (consulte Saída formatada).

Se você está preocupado com a portabilidade de seus programas para sistemas diferentes do GNU, você também deve estar ciente de que os descritores de arquivo não são tão portáveis ​​quanto os fluxos. Você pode esperar que qualquer sistema rodando ISO C suporte streams, mas sistemas não GNU podem não suportar descritores de arquivo, ou podem apenas implementar um subconjunto das funções GNU que operam em descritores de arquivo. A maioria das funções do descritor de arquivo na GNU C Library estão incluídas no padrão POSIX.1, entretanto.

Suraj Jain
fonte