#+title: Curso Básico da Linguagem C #+subtitle: Aula 15: Abertura de arquivos para escrita #+author: Blau Araujo #+startup: show2levels #+options: toc:3 * Aula 15: Abertura de arquivos para escrita [[https://youtu.be/vL8vy3krcKc][Vídeo desta aula]] ** Modos de abertura de arquivos Em relação ao sentido do fluxo de dados, nós podemos realizar duas operações com arquivos abertos: leitura e escrita. Com a função =fopen=, isso é definido em seu segundo argumento através de uma /string de modo/: | String | Modo | Descrição | |--------+---------+---------------------------------------------------------------------------------------------------| | ="r"= | Leitura | Abre o arquivo para leitura a partir de seu início. Se o arquivo não existir, causa um erro. | | ="w"= | Escrita | Apaga os dados originais do arquivo para escrever novos. Se o arquivo não existir, ele é criado. | | ="a"= | /Append/ | Abre o arquivo para acrescentar novos dados ao seu final. Se o arquivo não existir, ele é criado. | Na chamada de sistema =open=, as strings de modo seriam equivalentes às /flags/: - ="r"=: =O_RDONLY= - ="w"=: =O_WRONLY | O_CREAT | O_TRUNC= - ="a"=: =O_WRONLY | O_CREAT | O_APPEND= #+begin_quote As /flags/ múltiplas são passadas como operações /OR bit-a-bit/. #+end_quote *** Modos complementares Incluindo o caractere =+= ao final da string de modo, também será possível realizar a operação oposta: | String | Modo | Descrição | |--------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------| | ="r+"= | Leitura e escrita | Posiciona o ponteiro interno no início do arquivo para leitura e escrita. Se o arquivo não existir, causa um erro. | | ="w+"= | Escrita e leitura | Apaga os dados originais do arquivo para escrever novos e ler o que for escrito. Se o arquivo não existir, ele é criado. | | ="a+"= | /Append/ e leitura | Posiciona o ponteiro interno no fim do arquivo para leitura e para acrescentar novos dados. Se o arquivo não existir, ele é criado. | #+begin_quote Nós voltaremos a este assunto na próxima aula, mas deve ser evidente que precisaremos controlar o ponteiro interno do arquivo para realizar operações de leitura e escrita em um mesmo /stream/. #+end_quote *** Modos texto e binário Sistemas /Unix-like/ não fazem distinção entre arquivos texto e binários em operações de entrada e saída (I/O). Portanto, o caractere =b=, que pode ser incluído ao final ou entre os caracteres da string de modo, não terá efeito e só precisaria ser utilizado no caso da possibilidade do programa ser portado para outros sistemas. ** Modos de escrita Em termos gerais, as etapas de trabalho com arquivos abertos para escrita ou /append/ são os mesmos de quando falamos da leitura: - Abertura do arquivo para obter um /stream/; - Processamento dos dados; - Fechamento do stream. *** Abertura de um arquivo para escrita ("w") Neste exemplo, o arquivo =linha.txt= será criado (ou truncado, se já existir) para receber uma linha digitada pelo usuário no terminal: #+begin_src c // Abertura do arquivo para escrita... char *file = "linha.txt"; FILE *stream = fopen(file, "w"); if (!stream) { perror("Erro na abertura do arquivo"); return EXIT_FAILURE; } // Processamento... char line[BUFSIZ]; // Buffer para receber a linha digitada. fgets(line, BUFSIZ, stdin); // Lê a digitação no terminal. fprintf(stream, "%s", line) // Copia a string no buffer para o arquivo. // Fechamento do arquivo... fclose(stream); #+end_src Assim, toda vez que o programa for executado, seu conteúdo será substituído pelo que nós digitarmos (exceto na primeira vez, quando o arquivo for criado). *** Abertura de um arquivo para append ("a") Para que o arquivo =linha.txt= receba novas linhas a cada execução do exemplo anterior, basta trocar a string de modo: #+begin_src c // Abertura do arquivo para append... char *file = "linha.txt"; FILE *stream = fopen(file, "a"); if (!stream) { perror("Erro na abertura do arquivo"); return EXIT_FAILURE; } // Processamento... char line[BUFSIZ]; // Buffer para receber a linha digitada. fgets(line, BUFSIZ, stdin); // Lê a digitação no terminal. fprintf(stream, "%s", line) // Copia a string no buffer para o arquivo. // Fechamento do arquivo... fclose(stream); #+end_src ** Notas gerais - Enquanto o arquivo estiver aberto, nós podemos realizar diversas operações de escrita. - No caso do modo ="w"=, o conteúdo anterior do arquivo só será truncado na sua abertura, não a cada escrita com o arquivo já aberto. - Toda vez que algo é escrito no arquivo, seu ponteiro interno é posicionado no byte seguinte ao último byte escrito.