Respostas:
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 FILE
ponteiro é uma construção de nível de biblioteca padrão C, usada para representar um arquivo. O FILE
encapsula o descritor de arquivo e adiciona buffering e outros recursos para tornar o I / O mais fácil.
Você passa FILE
ponteiros para funções C padrão, como fread()
e fwrite()
.
fd
é o primeiro argumento para read()
. Por que você chama isso de pelado?
FILE *
tipo da biblioteca padrão , o descritor de arquivo inteiro é "menos empacotado", ou seja, "nu".
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()
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 FILE
estrutura de volta. A FILE
estrutura 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 FILE
estrutura, ou seja, fprintf()
e família.
Não há problemas de desempenho usando qualquer um.
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);
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;
Deseja adicionar pontos que podem ser úteis.
SOBRE FILE *
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
Geralmente é usado para IPC.
Fornece controle de baixo nível para arquivos em sistemas * nix. (Dispositivos, arquivos, soquetes, etc), portanto, mais poderoso que o FILE *
.
fdopen()
para fazer coisas como IPC e dispositivos com FILE*
?
FILE*
, mas pode criar um a FILE*
partir de um descritor de arquivo ( fdopen()
) e, posteriormente, fechar o FILE
irá 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.
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).
Apenas uma nota para encerrar a discussão (se estiver interessado) ....
fopen
pode ser inseguro e você provavelmente deve usar fopen_s
ou open
com bits exclusivos definidos. C1X está oferecendo x
modos, assim você pode fopen
com 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 .
fopen_s
nã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)
?
As chamadas do sistema usam principalmente o descritor de arquivo, por exemplo read
e 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.
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.