Obra: Programar em C/Entrada e saída em arquivos
trabalhando com arquivos já vimos como podemos receber enviar dados para usuário através do teclado da tela agora veremos também como ler gravar dados em arquivos que aliás muito importante ou até essencial em muitas aplicações assim como as funções de entrada saída padrão teclado tela as funções de entrada saída em arquivos estão declaradas no cabeçalho stdio que significa standard input output aliás as funções para manipulação de arquivos são muito semelhantes às usadas para entrada saída padrão como já dissemos na seção sobre entrada saída padrões manipulação de arquivos também se dá por meio de fluxos streams na manipulação de um arquivo há basicamente três etapas que precisam ser realizadas abrir arquivo ler ou gravar os dados desejados fechar arquivo em todas as operações realizadas com arquivos envolvem seu identificador de fluxo que uma variável do tipo file sobre qual não cabe agora falar para declarar um identificador de fluxo faça como se fosse uma variável normal file fp não se esqueça do asterisco abrindo fechando um arquivo não primeira coisa que se deve fazer para manipular um arquivo abri lo para isso usamos função fopen sua sintaxe file fopen char nome_do_arquivo char modo_de_acesso nome do arquivo deve ser uma string ou com caminho completo por exemplo usr share appname app conf ou documentos nomes txt ou caminho em relação ao diretório atual nomes txt app conf do arquivo que se deseja abrir ou criar modo de acesso uma string que contém uma seqüência de caracteres que dizem se arquivo será aberto para gravação ou leitura depois de aberto arquivo você só poderá executar os tipos de ação previstos pelo modo de acesso não poderá ler de um arquivo que foi aberto somente para escrita por exemplo os modos de acesso estão descritos na tabela seguir modo significado abre arquivo somente para leitura arquivo deve existir vem do inglês read ler abre arquivo para leitura escrita arquivo deve existir abre arquivo somente para escrita no início do arquivo apagará conteúdo do arquivo se ele já existir criará um arquivo novo se não existir vem do inglês write escrever abre arquivo para escrita leitura apagando conteúdo pré existente abre arquivo para escrita no final do arquivo não apaga conteúdo pré existente vem do inglês append adicionar apender abre arquivo para escrita no final do arquivo leitura em ambientes dos windows ao ler arquivos binários por exemplo programas executáveis ou certos tipos de arquivos de dados deve se adicionar caractere ao final da string de modo por exemplo wb ou para que arquivo seja lido gravado corretamente isso necessário porque no modo texto padrão quando não adicionado ocorrem algumas traduções de caracteres por exemplo terminação de linha substituída apenas por na leitura que poderiam afetar leitura gravação dos arquivos binários indevidamente inserindo ou suprimindo caracteres valor de retorno da função fopen muito importante ele identificador do fluxo que você abriu só com ele que você conseguirá ler escre
muito importante ele identificador do fluxo que você abriu só com ele que você conseguirá ler escrever no arquivo aberto se houver um erro na abertura criação do arquivo função retornará valor null erro geralmente acontece por duas razões arquivo não existe caso tenha sido requisitado para leitura usuário atual não tem permissão para abrir arquivo com modo de acesso pedido por exemplo arquivo somente leitura ou está bloqueado para gravação por outro programa ou pertence outro usuário não tem permissão para ser lido por outros ao terminar de usar um arquivo você deve fechá lo isso feito pela função fclose int fclose file fluxo único argumento identificador do fluxo retornado por fopen valor de retorno indica sucesso da operação com valor zero fechar um arquivo faz com que qualquer caractere que tenha permanecido no buffer associado ao fluxo de saída seja gravado mas que este buffer quando você envia caracteres para serem gravados em um arquivo estes caracteres são armazenados temporariamente em uma área de memória buffer em vez de serem escritos em disco imediatamente quando buffer estiver cheio seu conteúdo escrito no disco de uma vez razão para se fazer isto tem ver com eficiência nas leituras gravações de arquivos se para cada caractere que fôssemos gravar tivéssemos que posicionar cabeça de gravação em um ponto específico do disco apenas para gravar aquele caractere as gravações seriam muito lentas assim estas gravações só serão efetuadas quando houver um volume razoável de informações serem gravadas ou quando arquivo for fechado função exit fecha todos os arquivos que um programa tiver aberto função fflush força gravação de todos os caracteres que estão no buffer para arquivo exemplo um pequeno exemplo apenas para ilustrar abertura fechamento de arquivos include int main file fp fp fopen readme if fp null printf houve um erro ao abrir arquivo return printf arquivo readme criado com sucesso fclose fp return arquivos pré definidos na biblioteca padrão do existem alguns fluxos pré definidos que não precisam nem devem ser abertos nem fechados stdin dispositivo de entrada padrão geralmente teclado stdout dispositivo de saída padrão geralmente vídeo stderr dispositivo de saída de erro padrão geralmente vídeo stdaux dispositivo de saída auxiliar em muitos sistemas associado porta serial stdprn dispositivo de impressão padrão em muitos sistemas associado porta paralela escrevendo em arquivos para escrever em arquivos há quatro funções das quais três são análogas às usadas para saída padrão saída padrão arquivos explicação putchar fputc imprime apenas um caractere puts fputs imprime uma string diretamente sem nenhuma formatação printf fprintf imprime uma string formatada fwrite grava dados binários para um arquivo seguir apresentamos os protótipos dessas funções void fputc int caractere file fluxo void fputs char string file fluxo void fprintf file fluxo char formatação int fwrite void dados int int num_elementos file fluxo sintaxe quase igual de pri
xo char formatação int fwrite void dados int int num_elementos file fluxo sintaxe quase igual de printf só necessário adicionar identificador de fluxo no início fwrite esta função envolve os conceitos de ponteiro vetor que só serão abordados mais tarde função fwrite funciona como sua companheira fread porém escreve no arquivo seu protótipo unsigned fwrite void buffer int numero_de_bytes int count file fp função retorna número de itens escritos este valor será igual count menos que ocorra algum erro exemplo abaixo ilustra uso de fwrite fread para gravar posteriormente ler uma variável float em um arquivo binário include include int main file pf float pi float pilido if pf fopen arquivo bin wb null abre arquivo binário para escrita printf erro na abertura do arquivo exit if fwrite pi sizeof float pf escreve variável pi printf erro na escrita do arquivo fclose pf fecha arquivo if pf fopen arquivo bin rb null abre arquivo novamente para leitura printf erro na abertura do arquivo exit if fread pilido sizeof float pf le em pilido valor da variável armazenada anteriormente printf erro na leitura do arquivo printf no valor de pi lido do arquivo pilido fclose pf return nota se uso do operador sizeof que retorna tamanho em bytes da variável ou do tipo de dados fputc função fputc primeira função de escrita de arquivo que veremos seu protótipo int fputc int ch file fp escreve um caractere no arquivo programa seguir lê uma string do teclado escreve caractere por caractere em um arquivo em disco arquivo arquivo txt que será aberto no diretório corrente include include int main file fp char string int fp fopen arquivo txt arquivo ascii para escrita if fp printf erro na abertura do arquivo exit printf entre com string ser gravada no arquivo gets string for stringi fputc stringi fp grava string caractere caractere fclose fp return depois de executar este programa verifique conteúdo do arquivo arquivo txt você pode usar qualquer editor de textos você verá que string que você digitou está armazenada nele leitura de arquivos novamente há quatro funções das quais três se assemelham às usadas para saída padrão saída padrão arquivos explicação getchar fgetc recebe apenas um caractere gets fgets lê uma string geralmente uma linha inteira scanf fscanf recebe uma string formatada fread lê dados binários de um arquivo int fgetc file fluxo void fgets char string int tamanho file fluxo void fscanf file fluxo char formatação int fread void dados int int num_elementos file fluxo fgetc está função requer como parâmetro indicador de fluxo do arquivo retorna um caractere do arquivo ou eof caso ocorra um erro ou final do arquivo seja atingido podendo ser verificado respectivamente por ferror feof exemplo include include int main file fl int if fl fopen caminho do arquivo null perror erro fopen exit exit_failure while fgetc fl eof printf caractere lido if eof feof fl ferror fl perror erro fgetc fclose fl return exit_success fgets ao chamar função fgets você deve fornecer ponteiro p
erro fgetc fclose fl return exit_success fgets ao chamar função fgets você deve fornecer ponteiro para string onde os dados lidos devem ser guardados além do tamanho máximo dos dados serem lidos para que memória reservada string não seja ultrapassada para se ler uma string num arquivo podemos usar fgets cujo protótipo char fgets char str int tamanho file fp função recebe argumentos string ser lida limite máximo de caracteres serem lidos ponteiro para file que está associado ao arquivo de onde string será lida função lê string até que um caracter de nova linha seja lido ou tamanho caracteres tenham sido lidos se caracter de nova linha for lido ele fará parte da string que não acontecia com gets função fgets semelhante função gets porém além dela poder fazer leitura partir de um arquivo de dados incluir caracter de nova linha na string ela ainda especifica tamanho máximo da string de entrada como vimos função gets não tinha este controle que poderia acarretar erros de estouro de buffer portanto levando em conta que ponteiro fp pode ser substituído por stdin como vimos acima uma alternativa ao uso de gets usar seguinte construção fgets str tamanho stdin fscanf sintaxe quase igual de scanf só necessário adicionar identificador de fluxo no início fscanf função fscanf funciona como função scanf diferença que fscanf lê de um arquivo não do teclado do computador protótipo int fscanf file fp char str include include int main file char str printf entre com um nome para arquivo le um nome para arquivo ser aberto gets str if fopen str caso ocorra algum erro na abertura do arquivo programa aborta automaticamente printf erro impossivel abrir arquivo exit fprintf este um arquivo chamado str fclose se nao houve erro imprime no arquivo fecha fopen str abre novamente para leitura while feof fscanf printf fclose return fread essa função envolve os conceitos de ponteiro vetor que só serão abordados mais tarde podemos escrever ler blocos de dados para tanto temos as funções fread fwrite protótipo de fread unsigned fread void buffer int numero_de_bytes int count file fp buffer região de memória na qual serão armazenados os dados lidos número de bytes tamanho da unidade ser lida count indica quantas unidades devem ser lidas isto significa que número total de bytes lidos numero_de_bytes count função retorna número de unidades efetivamente lidas este número pode ser menor que count quando fim do arquivo for encontrado ou ocorrer algum erro quando arquivo for aberto para dados binários fread pode ler qualquer tipo de dados movendo pelo arquivo fseek para se fazer procuras acessos randômicos em arquivos usa se função fseek esta move posição corrente de leitura ou escrita no arquivo de um valor especificado partir de um ponto especificado seu protótipo int fseek file fp long numbytes int origem parâmetro origem determina partir de onde os numbytes de movimentação serão contados os valores possíveis são definidos por macros em stdio são nome valor significado seek_set iníci
dos os valores possíveis são definidos por macros em stdio são nome valor significado seek_set início do arquivo seek_cur ponto corrente no arquivo seek_end fim do arquivo tendo se definido partir de onde irá se contar numbytes determina quantos bytes de deslocamento serão dados na posição atual rewind volta para começo do arquivo de um fluxo feof eof end of file indica fim de um arquivo às vezes necessário verificar se um arquivo chegou ao fim para isto podemos usar função feof ela retorna não zero se arquivo chegou ao eof caso contrário retorna zero seu protótipo int feof file fp outra forma de se verificar se final do arquivo foi atingido comparar caractere lido por getc com eof programa seguir abre um arquivo já existente lê caracter por caracter até que final do arquivo seja atingido os caracteres lidos são apresentados na tela include include int main file fp char fp fopen arquivo txt arquivo ascii para leitura if fp printf erro na abertura do arquivo exit while getc fp eof enquanto não chegar ao final do arquivo printf imprime caracter lido fclose fp return verifique exemplo include include include int main file char str frase este um arquivo chamado int printf entre com um nome para arquivo gets str le um nome para arquivo ser aberto if fopen str caso ocorra algum erro na abertura do arquivo printf erro impossivel abrir arquivo exit programa aborta automaticamente strcat frase str for frasei putc frasei fclose se nao houve erro imprime no arquivo fecha fopen str abre novamente para leitura getc le primeiro caracter while feof enquanto não se chegar no final do arquivo printf imprime caracter na tela getc le um novo caracter no arquivo fclose fecha arquivo outras funções função explicação remove remove um arquivo especificado ferror perror protótipo de ferror int ferror file fp função retorna zero se nenhum erro ocorreu um número diferente de zero se algum erro ocorreu durante acesso ao arquivo se torna muito útil quando queremos verificar se cada acesso um arquivo teve sucesso de modo que consigamos garantir integridade dos nossos dados na maioria dos casos se um arquivo pode ser aberto ele pode ser lido ou gravado porém existem situações em que isto não ocorre por exemplo pode acabar espaço em disco enquanto gravamos ou disco pode estar com problemas não conseguimos ler etc uma função que pode ser usada em conjunto com ferror função perror print error cujo argumento uma string que normalmente indica em que parte do programa problema ocorreu include include int main file pf char string if pf fopen arquivo txt null printf nnao consigo abrir arquivo exit do printf ndigite uma nova string para terminar digite gets string fputs string pf putc pf if ferror pf perror erro na gravacao fclose pf exit while strlen string fclose pf