HOWTO · C

Use o redirecionamento de arquivo em C

Este artigo demonstra como usar o redirecionamento de arquivo em C

Nesta página

Para redirecionar a entrada ou a saída de um programa C pela linha de comando, use os operadores do shell <, > e >>. O shell conecta os fluxos padrão do programa a arquivos; no código C, você pode abrir um arquivo pelo nome com fopen ou alterar um fluxo padrão com freopen. São formas relacionadas de lidar com dados, mas correspondem a operações diferentes.

Entendendo o redirecionamento de arquivos em C

Um processo C começa com três fluxos padrão: stdin para entrada, stdout para a saída normal e stderr para mensagens de diagnóstico. Em geral, o shell os conecta ao terminal. O redirecionamento altera essas conexões ao iniciar o programa, que pode continuar chamando fgets, printf ou fprintf(stderr, ...) sem precisar saber se um fluxo está ligado ao terminal ou a um arquivo.

Em contrapartida, fopen retorna um FILE * separado, que o código pode ler ou gravar diretamente. Use essa função quando o programa precisar escolher entre arquivos, lidar com vários arquivos ao mesmo tempo ou controlar o tempo de vida deles. Use o redirecionamento do shell quando quem executa o programa deve escolher a origem da entrada ou o destino da saída.

Redirecionando a saída do programa com > e »

Este pequeno programa escreve uma linha em stdout:

Execute este exemplo:

O código e os rótulos visíveis do exemplo permanecem em inglês.

#include <stdio.h>

int main(void) {
    puts("Report complete");
    return 0;
}

A linha do programa vai para stdout; este exemplo não vem acompanhado de uma transcrição de execução. Depois de compilá-lo com o nome report, execute ./report > report.txt para criar ou substituir report.txt. Para acrescentar conteúdo ao final, use ./report >> report.txt. O operador > trunca o arquivo de destino existente antes de o programa começar, enquanto >> grava no fim dele. A sintaxe do shell e os comandos de compilação disponíveis variam conforme a plataforma.

O shell abre o destino redirecionado. Se essa abertura falhar, ele informa o problema e, normalmente, não inicia o programa. O programa não consegue detectar isso como uma falha de fopen, pois não foi ele que abriu o destino. Para salvar as mensagens de diagnóstico em outro arquivo, use ./report > report.txt 2> errors.txt; 2> redireciona o descritor de arquivo convencional usado por stderr.

Redirecionando a entrada do programa com <

Leia de stdin quando quem executa o programa deve escolher a origem da entrada. Este programa lê linhas até o arquivo redirecionado chegar ao fim:

O código e os rótulos visíveis do exemplo permanecem em inglês.

#include <stdio.h>

int main(void) {
    char line[128];

    while (fgets(line, sizeof line, stdin) != NULL) {
        if (fputs(line, stdout) == EOF) {
            perror("writing stdout");
            return 1;
        }
    }

    if (ferror(stdin)) {
        perror("reading stdin");
        return 1;
    }
    return 0;
}

Compile o programa com o nome copy-input e execute ./copy-input < input.txt. fgets lê no máximo um caractere a menos que a capacidade do buffer, acrescenta um caractere nulo terminador e mantém a quebra de linha se ler uma. Por isso, uma linha longa pode ser retornada em várias partes. Depois do laço, verifique ferror para distinguir uma falha de leitura do fim normal do arquivo. O comportamento do exemplo decorre das operações de fluxo C mostradas; não há uma saída observada fornecida aqui.

Redirecionando fluxos padrão dentro de um programa C

Quando o próprio programa precisa escolher um destino, freopen pode reabrir um fluxo padrão. A função recebe um caminho, um modo como "w" ou "a" e o fluxo que será reaberto. Por exemplo, freopen("run.log", "a", stdout) direciona a saída padrão subsequente para o fim de run.log. Antes de gravar, verifique o valor retornado: a função retorna NULL se a reabertura falhar. Isso altera o fluxo do processo, ao contrário de fopen, que fornece outro fluxo sem alterar stdout.

Use essa opção quando o redirecionamento fizer parte do comportamento do próprio programa. Se quem o executa deve decidir o destino, mantenha stdout inalterado e use > ou >>. freopen faz parte do C padrão, mas os detalhes de reabertura de um fluxo após uma falha podem depender da implementação. Trate um resultado NULL e não continue como se o redirecionamento tivesse sido bem-sucedido.

Tratando erros e escolhendo a abordagem certa

Verifique todas as operações que podem falhar. Teste fopen e freopen antes de usar o fluxo retornado, confira se funções de saída como fprintf ou fputs falharam e verifique fclose quando for importante confirmar que a saída em buffer chegou ao arquivo. Em laços de leitura, um resultado NULL de fgets pode indicar o fim do arquivo ou um erro de leitura; consulte ferror para distinguir os casos. perror pode informar uma mensagem do sistema operacional referente a uma falha associada ao errno atual.

Não dimensione um buffer de linha com base no tamanho em bytes informado para um arquivo: a entrada pode vir de um pipe ou terminal, e uma linha pode ser maior que o buffer escolhido. Um buffer de tamanho fixo, usado com chamadas repetidas a fgets, serve quando é aceitável processar os dados em partes. Para uma linha lógica de comprimento arbitrário, aumente um buffer conforme os trechos chegam e verifique os limites de alocação e de aritmética, ou use um recurso de leitura de linha específico da plataforma, indicando seus limites de portabilidade.

Escolha o redirecionamento do shell para conectar os fluxos padrão durante uma execução, fopen para gerenciar um arquivo adicional em C e freopen quando o programa precisar substituir um fluxo padrão. Mantenha as mensagens de diagnóstico em stderr quando a saída normal estiver redirecionada e verifique as falhas na camada que realiza a operação.