AULA 22 - Programação 1 - Engenharia - MediaWiki do Campus São José
2.3.1 Referência a um arquivo
2.3.2 No Linux/Unix tudo é arquivo
3.3 Escrevendo e lendo um arquivo texto de forma formatada
3.3.1 Escrevendo de forma formatada com fprintf
3.3.2 Lendo de forma formata com fscanf
3.3.3 Exercício 1
3.3.4 Exemplo de gravação na forma texto de uma tabela com estruturas
3.4 Escrevendo e Lendo usando fgets e fputs
3.4.1 Exercício 1
3.4.2 Exemplo 3
3.5 Exemplo de gravação/leitura de uma tabela de estruturas na forma binária usando fwrite e fread
3.6 Exemplo de gravação de uma tabela com estruturas contendo ponteiros
3.7 Ainda funções de acesso a arquivos - posicionando cursor sobre o arquivo
Após esta aula o aluno terá:
Noções básicas do sistema de arquivos no Linux
Capacidade de desenvolver aplicações simples em C e que fazem acesso a arquivos com funções de alto nível da biblioteca.
Quanto a forma como os dados são armazenados, podemos dizer que os arquivos são binários ou texto. Qualquer um deles armazena bits mas os bytes de um arquivo texto devem ser interpretados como códigos ASCII e são organizados em linhas.
Se abrir um arquivo texto com o "vi" pode-se "ver" os bytes armazenados no arquivo:
Entrar em modo comando (SHIFT :) e fazer:
Ao abrir um arquivo a partir de um programa em C, pode-se ter comportamentos diferentes se optar por abrir em modo texto ou binário
Ver link da Aula Prof.Rodrigo de Oliveira
Em sistemas do porte do Linux e Windows, por questões de segurança e controle, todo acesso a arquivo é realizado através de código do sistema operacional. Desta forma, um programa que deseja acessar um arquivo deve gerar uma CHAMADA AO SISTEMA. O Linux (assim como outros sistemas) possui uma API (Application Programming Interface) bem definida, na forma de um conjunto de chamadas que permitem realizar uma série de funcionalidades (serviços) para os processos (programas em execução).
O acesso em alto nível é realizado usando uma estrutura do tipo FILE definida no stdio.h. Todo acesso passa inicialmente por abrir o arquivo (função fopen), ler/escrever (várias funções, tipo fread(), fwrite()) e fechar o arquivo (fclose()). As principais funções são mostradas na tabela abaixo.
fopen abrir arquivo retorna um ponteiro para FILE dado o nome do arquivo
fclose fechar arquivo descrito por FILE
fprintf escrever no arquivo de forma formatada
fscanf ler de um arquivo de forma formatada A função retorna o "define" (um inteiro) EOF (end-of-file) quando não existe mais dados a serem lidos.
fputc escrever um caracter do arquivo
fgetc ler um caracter do arquivo
fputs escrever string no arquivo
fgets ler string no arquivo
fwrite escrever dados de forma não formatada
fread ler dados de forma não formada
Escrevendo e lendo um arquivo texto de forma formatada
Nos exemplos que se seguem, serão usadas as funções fopen e fclose, para abrir e fechar arquivo e fprintf() e fscanf() para leitura e escrita. A forma é similar ao printf e scanf, a não ser pelo fato de que a escrita e leitura é realizada no arquivo indicado por p_arq
Observar que um arquivo que está sendo acessado possui uma posição corrente de acesso de forma que uma nova leitura ou escrita sempre avança para "frente" nos dados do arquivo.
Escrevendo de forma formatada com fprintf
/*escrevendo no arquivo IFSC.txt*/
Para ver o que foi escrito no arquivo faça:
Use o vi para ver os bytes armazenados no arquivo IFSC.TXT.
Lendo de forma formata com fscanf
Para ler o arquivo IFSC.txt pode-se usar o fscanf().
/*lendo do arquivo IFSC.txt*/
Note que o fscanf se comporta de forma similar ao scanf. A função retorna o define EOF (end-of-file) quando não existe mais dados a serem lidos.
Exemplo 1: lendo conteúdo com fscanf
Neste exemplo o programa abre um arquivo texto chamado data.txt que contém uma linha com dia, mês e ano separado por espaço em branco. O arquivo deve ser criado previamente.
Crie o arquivo data.txt e coloque dados dentro da forma:
arq = fopen("data.txt", "r");
printf("Arquivo aberto com sucesso, continuando...\n");
printf("Não foi possível abrir o arquivo\n");
fscanf(arq, "%d/%d/%d", &dia, &mes, &ano);
printf("O dia eh: %d/%d/%d\n", dia, mes, ano);
Exemplo 2: escrevendo e lendo conteúdo em arquivos
O programa abaixo escreve a data (ver exemplo anterior) em um arquivo. Ele pode ser usado conjuntamente com o programa do exercício anterior para inserir dados em um arquivo.
FILE *pont_arq; // cria variável ponteiro para o arquivo
char palavra[20]; // variável do tipo string
//abrindo o arquivo com tipo de abertura w
pont_arq = fopen("arquivo_palavra.txt", "w"); //modo padrão de abertura do arquivo é texto (adicionar b se quiser binário - Ex "rb", "wb", etc)
//testando se o arquivo foi realmente criado
if (pont_arq != NULL)
printf("Escreva uma palavra para testar gravacao de arquivo: ");
scanf("%[^\n]s", palavra); // [^\n] ler espaço como caracter válido
//escreve no arquivo texto:"2/5/2006"
fprintf(pont_arq, "%d/%d/%d\n", 2, 5, 2006);
//usando fprintf para armazenar a string no arquivo
fprintf(pont_arq, "%s\n", palavra);
//usando fclose para fechar o arquivo
printf("Dados gravados com sucesso\n!");
Implementar um programa que soma duas matrizes fornecidas em dois arquivos texto separados: MatA.dat e MatB.dat. Colocar o resultado em um arquivo chamado MatC.dat.
Exemplo de gravação na forma texto de uma tabela com estruturas
#define TAM_TAB2 3
struct tipo_registro2{
float nota_final;
} tab_registros[TAM_TAB2] = {
{"alfa da silva", 10, 9.5},
{"beta da silva", 30, 6.9},
{"epson da silva", 20, 7.5},
Esta função mostra como salvar a tabela de estruturas na forma de um arquivo texto contendo uma estrutura por lionha. Os campos são separados com :
void salvar_am_arq()
if ((ptr = fopen("teste.dat", "w+"))== NULL) {
printf("Erro na abertura de arquivo\n");
for (i=0;i<TAM_TAB2;i++)
fprintf (ptr, "%s:%d:%f\n", tab_registros[i].nome, tab_registros[i].idade, tab_registros[i].nota_final);
Esta função mostra como recuperar a tabela de estruturas na forma de um arquivo texto contendo uma estrutura por linha. Os campos são separados com :
void restaurar_tab_do_arq()
int ret=0,i=0;
if ((ptr = fopen("teste.dat", "r"))== NULL) {
while  (ret != EOF) {
ret = fscanf (ptr, " %[^:]:%d:%f", tab_registros[i].nome, &tab_registros[i].idade, &tab_registros[i].nota_final);
if (ret==3) { /* ret contém o número de itens lidos */
printf("REGISTRO %d %s %d %f\n",i,tab_registros[i].nome, tab_registros[i].idade, tab_registros[i].nota_final);
} else if (ret!=EOF)
printf("Provavelmente existe um erro no arrquivo de dados\n");
salvar_am_arq();
restaurar_tab_do_arq();
Escrevendo e Lendo usando fgets e fputs
Neste exemplo usaremos as funções fgetc e fputc para ler e escrever caracteres ASCII nos arquivos. Seja um programa que conta o número de ocorrências do caracter 'a', remova esses caracteres 'a' e salve os caracteres em um novo arquivo destino:
puts("Não conseguiu escrever no arquivo\n");
Exemplo 4: escrevendo e lendo string em arquivos
char texto_str[20];
//abrindo o arquivo_frase em modo "somente leitura"
pont_arq = fopen("arquivo_palavra.txt", "r");
//enquanto não for fim de arquivo o looping será executado
//e será impresso o texto
while(fgets(texto_str, 20, pont_arq) != NULL)
printf("%s", texto_str);
//fechando o arquivo
Neste exemplo vamos explorar o modo de abertura do arquivo para fazer um append (escrever no final do arquivo). Ver time() e ctime() em http://www.cplusplus.com/reference/ctime/.
/* ler a hora/data do sistema e armazenar em ltime */
/* escrever hora/data lida em arquivo, mas converter antes para string (ctime) */
Exemplo de gravação/leitura de uma tabela de estruturas na forma binária usando fwrite e fread
struct tipo_registro2 aux[TAM_TAB2];
fwrite (tab_registros, sizeof(struct tipo_registro2),TAM_TAB2,ptr);
ret = fread(aux,sizeof(struct tipo_registro2),TAM_TAB2,ptr);
printf("número de itens lidos = %d\n", ret);
printf("%s\n", aux[2].nome);
Exemplo de gravação de uma tabela com estruturas contendo ponteiros
Observe no exemplo abaixo que um vetor de estruturas (tabela) contendo ponteiros pode ter problemas no seu salvamento, caso as áreas apontadas não sejam gravadas. A tabela tab_registros2 se for gravada com salvar_em_arq2() perderá dados pois os dados apontados por nome não serão salvos com fwrite. Pode-se contornar este problema gravando cada estrutura em uma linha de forma formatada, separada por delimitadores. Ver função salvar_am_arq2_vOK(). A recuperação dos dados deve prever a reconstituição da tabela (ver restaurar_tab_do_arq2()).
Note o significado das formatações usadas no scanf/fscanf: [1]
qualquer caracter em branco na string de formato faz com que a função ignore quaisquer espaço em branco, newline, tab ou qualquee
} tab_registros2[TAM_TAB2] = {
{"alfa", 10},
{"beta", 30},
{"epson", 20},
void salvar_em_arq2()
/* PROBLEMAS... - a estrutura tem ponteiros... */
ptr =fopen("teste2.dat", "w+");
fwrite(tab_registros2, sizeof(struct tipo_registro2),TAM_TAB2,ptr);
void salvar_am_arq2_vOK()
fprintf (ptr, "%s:%d\n", tab_registros2[i].nome, tab_registros2[i].idade);
void print_tab2()
for (i=0;i<TAM_TAB2;i++) {
printf ("%s:%d\n", tab_registros2[i].nome, tab_registros2[i].idade);
void restaurar_tab_do_arq2()
int ret,i=0;
ptr =fopen("teste2.dat", "r");
while  (ret!=EOF) {
ret=fscanf (ptr, " %[^:]:%d", buffer,&tab_registros2[i].idade);
if (ret==2) {
tab_registros2[i].nome=(char *)malloc(strlen(buffer));
strcpy(tab_registros2[i].nome, buffer);
printf("i=%d ret=%d %s %d\n",i,ret,tab_registros2[i].nome, tab_registros2[i].idade);
salvar_am_arq2_vOK();
restaurar_tab_do_arq2();
print_tab2();
/* a fazer = liberar areas alocadas dinamicamente */
Ainda funções de acesso a arquivos - posicionando cursor sobre o arquivo
É possível entretanto modificar a posição deste cursor, tipicamente com as funções fseek() e rewind(). (ver [2]).
Escreva um programa que receba do usuário 5 números inteiros e o nome do arquivo no qual eles devem ser armazenados. Em seguida, ler do arquivo estes valores armazenados copiando-os para um vetor de inteiros e imprimindo na tela.
int i, temp, vet[5];
char nome_arq[20];
printf("Informe o nome do arquivo: ");
scanf("%[^\n]s",nome_arq);
if ((arq = fopen (nome_arq, "w+"))== NULL){
printf("Erro ao abrir o arquivo %s", nome_arq);
printf("informe um valor inteiro: ");
fprintf(arq, "%d", temp);
fprintf(arq, "\n");
rewind(arq);  //Retorna o indicador de posição do ponteiro FILE em relação ao arquivo para o seu início.
while ( !feof(arq) ){     //Retorna zero se o final do arquivo foi atingido e um valor não nulo caso contrário.
fscanf (arq, "%d", &vet[i]);
Disponível em "https://wiki.sj.ifsc.edu.br/index.php?title=AULA_22_-_Programação_1_-_Engenharia&oldid=182087"