C fopen vs open

219

Existe algum motivo (além dos sintáticos) que você gostaria de usar

FILE *fdopen(int fd, const char *mode);

ou

FILE *fopen(const char *path, const char *mode);

ao invés de

int open(const char *pathname, int flags, mode_t mode);

ao usar C em um ambiente Linux?

LJM
fonte
Você quis dizer fdopene openou fopene open?
User7116
Você não quer dizer fopen, não fdopen?
Onipotente 1/11/2009
9
fopenfaz parte da biblioteca C padrão, opennão é. Use fopenao escrever código portátil.
Aziz
Sim, eu quis dizer abrir. Acabei de atualizar, mas acho que o mesmo princípio se aplica.
LJM
6
@ Aziz, embora openseja uma função POSIX.
dreamlax

Respostas:

242

Primeiro, não há um motivo particularmente bom para usar fdopense fopené uma opção e opené a outra opção possível. Você não deveria ter usado openpara abrir o arquivo em primeiro lugar, se quiser FILE *. Portanto, incluir fdopennessa lista é incorreto e confuso porque não é muito parecido com os outros. Agora vou ignorá-lo porque a importante distinção aqui é entre um padrão C FILE *e um descritor de arquivo específico do SO.

Existem quatro razões principais para usar em fopenvez de open.

  1. fopenfornece IO de buffer que pode ser muito mais rápido do que o que você está fazendo open.
  2. fopen faz tradução de final de linha se o arquivo não for aberto no modo binário, o que pode ser muito útil se o seu programa for portado para um ambiente não-Unix (embora o mundo pareça estar convergindo apenas para LF (exceto redes baseadas em texto IETF) protocolos como SMTP e HTTP e outros)).
  3. A FILE *oferece a capacidade de usar fscanfe outras funções do stdio.
  4. Algum dia, seu código precisará ser portado para outra plataforma que ofereça suporte apenas ao ANSI C e não à openfunção.

Na minha opinião, a tradução de final de linha entra mais frequentemente em seu caminho do que ajuda você, e a análise de fscanfé tão fraca que você inevitavelmente acaba jogando fora em favor de algo mais útil.

E a maioria das plataformas que suportam C têm um open função.

Isso deixa a questão do buffer. Nos locais em que você está lendo ou gravando principalmente um arquivo sequencialmente, o suporte ao buffer é realmente útil e uma grande melhoria de velocidade. Mas isso pode levar a alguns problemas interessantes nos quais os dados não acabam no arquivo quando você espera que eles estejam lá. Você tem que lembrar defclose ou fflushnos momentos apropriados.

Se você estiver fazendo buscas (aka fsetposoufseek o segundo é um pouco mais difícil de usar de maneira compatível com os padrões), a utilidade do buffer diminui rapidamente.

Obviamente, meu preconceito é que eu tendem a trabalhar muito com soquetes, e existe o fato de que você realmente deseja fazer IO sem bloqueio (que FILE *falha totalmente no suporte de qualquer maneira razoável) sem buffer e muitas vezes requisitos complexos de análise realmente colorem minhas percepções.

Omniforme
fonte
4
Não vou questionar suas experiências, mas adoraria ouvi-lo elaborar um pouco sobre isso. Para quais tipos de aplicativos você acha que o buffer interno atrapalha? Qual é exatamente o problema?
Emil H
1
Não viu o último parágrafo. Ponto válido, IMHO. Até onde eu sei, a pergunta era sobre E / S de arquivo, no entanto.
Emil H
7
Esclarecer quando o buffer atrapalha. É quando você usa a busca. O seguinte leitura com qualquer comando ( fgets, fgetc, fscanf, fread), será sempre ler todo o tamanho do buffer (4K, 8K ou o que você definir). Usando a E / S direta, você pode evitar isso. Nesse caso, é ainda melhor usar em preadvez de um par de busca / leitura (1 syscall em vez de 2).
Patrick Schlüter 5/05
2
O tratamento de chamadas read()e interrupções write()é um quinto motivo conveniente para usar a família de funções libc.
Ncc 26/08/12
3
@ m-ric: Bem, essa é uma pergunta não relacionada, mas sim. Todas as plataformas suportadas ioctltambém suportam a filenochamada que recebe FILE *e retorna um número que pode ser usado em uma ioctlchamada. Tenha cuidado, porém. FILE *chamadas relacionadas podem interagir surpreendentemente com o uso ioctlpara alterar algo sobre o descritor de arquivo subjacente.
Onívoro 28/09/12
53

open()é uma chamada de sistema operacional de baixo nível. fdopen()converte um descritor de arquivo no nível do sistema operacional para a abstração de ARQUIVO de nível superior da linguagem C. fopen()chamadasopen() em segundo plano e fornece um ponteiro FILE diretamente.

Existem várias vantagens no uso de objetos FILE, em vez de descritores de arquivos brutos, que incluem maior facilidade de uso, mas também outras vantagens técnicas, como buffer interno. Especialmente, o buffer geralmente resulta em uma vantagem considerável de desempenho.

Emil H
fonte
3
Há alguma desvantagem em usar as versões 'f ...' em buffer do open?
LJM 01/11
5
@EU. Moser, sim, quando você já estiver armazenando dados em buffer e, portanto, o buffer adicional adiciona cópia desnecessária e sobrecarga de memória.
22430 Michael Aaron Safyan
6
na verdade, existem outras desvantagens. fopen()não fornece o mesmo nível de controle ao abrir arquivos, por exemplo, criar permissões, modos de compartilhamento e muito mais. normalmente open()e variantes proporcionam muito mais controle, perto do que o sistema operacional realmente fornece
Matt Joiner
2
Também existem casos extremos em que você mmaparquiva e faz alterações com a E / S normal (por incrível que pareça, no nosso projeto, e por boas razões reais), o buffer estaria no caminho.
Patrick Schlüter 5/05
Você também pode usar outras funções do sistema, como o uso de open () para pré-carregar arquivos no cache da página via readahead (). Eu acho que a regra geral é "use fopen a menos que você precise absolutamente de open ()", open () na verdade permite fazer coisas sofisticadas (configurando / não configurando O_ATIME e similares).
Tomas Pruzina
34

fopen vs aberto em C

1) fopené uma função de biblioteca enquanto opené uma chamada do sistema .

2) fopenfornece IO em buffer, que é mais rápido em comparação com o openque não é em buffer .

3) fopené portátil enquanto opennão portátil ( aberto é específico do ambiente ).

4) fopenretorna um ponteiro para uma estrutura FILE (FILE *) ; openretorna um número inteiro que identifica o arquivo.

5) A FILE *oferece a capacidade de usar o fscanf e outras funções do stdio.

Yogeesh HT
fonte
9
opené um padrão POSIX, por isso é bastante portátil
osvein
12

A menos que você faça parte dos 0,1% de aplicativos em que o uso opené um benefício real de desempenho, não há realmente uma boa razão para não usá-lo fopen. No que diz fdopenrespeito, se você não estiver jogando com descritores de arquivo, não precisará dessa chamada.

Stick with fopene sua família de métodos ( fwrite, fread, fprintf, et al) e você será muito satisfeito. Tão importante quanto isso, outros programadores ficarão satisfeitos com o seu código.

user7116
fonte
11

Se você tem um FILE *, você pode usar funções como fscanf, fprintfe fgetsetc. Se você tiver apenas o descritor de arquivo, você tem limitado (mas provavelmente mais rápido) rotinas de entrada e saída read, writeetc.

dreamlax
fonte
7

Usar abrir, ler, escrever significa que você precisa se preocupar com interações de sinal.

Se a chamada foi interrompida por um manipulador de sinal, as funções retornam -1 e configuram errno como EINTR.

Portanto, a maneira correta de fechar um arquivo seria

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
digy
fonte
4
Pois closeisso depende do sistema operacional. É incorreto executar o loop no Linux, AIX e em outros sistemas operacionais.
precisa
Além disso, o uso de leitura e gravação sofrerá o mesmo problema, ou seja, eles podem ser interrompidos por um sinal antes de processar totalmente a entrada / saída e o programador precisa lidar com essas situações, enquanto fread e fwrite tratam bem as interrupções de sinal.
Marcelo
6

open()é uma chamada de sistema e específica para sistemas baseados em Unix e retorna um descritor de arquivo. Você pode gravar em um descritor de arquivo usando write()outra chamada do sistema.
fopen()é uma chamada de função ANSI C que retorna um ponteiro de arquivo e é portátil para outros sistemas operacionais. Podemos escrever para um ponteiro de arquivo usandofprintf .

No Unix:
você pode obter um ponteiro de arquivo no descritor de arquivos usando:

fP = fdopen(fD, "a");

Você pode obter um descritor de arquivo no ponteiro do arquivo usando:

fD = fileno (fP);
Arun Chettoor
fonte
4

open () será chamado no final de cada uma das funções da família fopen () . open () é uma chamada do sistema e fopen () são fornecidos pelas bibliotecas, pois um wrapper funciona para facilitar o uso do usuário

theadnangondal
fonte
2

Alterei para open () de fopen () para o meu aplicativo, porque o fopen estava causando leituras duplas toda vez que eu executava o fopen fgetc. Leituras duplas perturbam o que eu estava tentando realizar. open () parece fazer o que você pede.

Ersatz Splatt
fonte
2

Depende também de quais sinalizadores são necessários para abrir. Com relação ao uso para escrita e leitura (e portabilidade), f * deve ser usado, conforme discutido acima.

Mas se basicamente quiser especificar mais do que sinalizadores padrão (como sinalizadores rw e anexar), você precisará usar uma API específica da plataforma (como POSIX aberto) ou uma biblioteca que abstraia esses detalhes. O padrão C não possui nenhum sinalizador.

Por exemplo, você pode querer abrir um arquivo, apenas se ele sair. Se você não especificar o sinalizador de criação, o arquivo deverá existir. Se você adicionar exclusivo para criar, ele criará o arquivo apenas se ele não existir. Existem muitos mais.

Por exemplo, nos sistemas Linux, há uma interface de LED exposta através do sysfs. Ele expõe o brilho do led através de um arquivo. Escrever ou ler um número como uma sequência que varia de 0 a 255. É claro que você não deseja criar esse arquivo e somente gravar se ele existir. O legal agora: use fdopen para ler / gravar este arquivo usando as chamadas padrão.

Ritualmaster
fonte
0

Ao abrir um arquivo usando fopen
antes de podermos ler (ou escrever) informações de (para) um arquivo em um disco, devemos abrir o arquivo. para abrir o arquivo, chamamos a função fopen.

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

este o modo de comportamento da função fopen
existem algumas causas durante o processo de buffer, pode expirar. portanto, ao comparar a chamada do sistema fopen (alto nível de E / S) para abrir (baixo nível de E / S), é mais rápido e apropriado do que o Fopen .

prashad
fonte
é aberto mais rápido do que abrir?
obayhan
sim, aberta é a chamada de sistema, o que é mais rápido do que fopen - @obayhan comparitively
prashad