HOWTO · C

Usar redirección de archivos en C

Este artículo muestra cómo utilizar la redirección de archivos en C

En esta página

Para redirigir desde la línea de comandos la entrada o la salida de un programa en C, usa los operadores del shell <, > y >>. El shell conecta los flujos estándar del programa con archivos; desde el código C, en cambio, puedes abrir un archivo con nombre mediante fopen o cambiar un flujo estándar con freopen. Son formas relacionadas de manejar datos, pero son operaciones distintas.

Cómo funciona la redirección de archivos en C

Un proceso C comienza con tres flujos estándar: stdin para la entrada, stdout para la salida normal y stderr para los mensajes de diagnóstico. Normalmente, el shell los conecta con la terminal. Al iniciar el programa, la redirección cambia esas conexiones, así que el programa puede seguir llamando a fgets, printf o fprintf(stderr, ...) sin saber si un flujo va a una terminal o a un archivo.

En cambio, fopen devuelve un FILE * independiente que el código puede leer o escribir directamente. Úsalo cuando el programa tenga que elegir entre varios archivos, manejar varios a la vez o controlar cuánto tiempo permanecen abiertos. Usa la redirección del shell cuando quien ejecuta el programa deba elegir el origen de la entrada o el destino de la salida.

Redirigir la salida del programa con > y »

Este programa sencillo escribe una línea en stdout:

Ejecuta este ejemplo:

El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.

#include <stdio.h>

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

La línea del programa se envía a stdout. Las cadenas literales del código de ejemplo permanecen en inglés; aquí no se incluye una transcripción de la ejecución. Después de compilarlo como report, ejecútalo con ./report > report.txt para crear o reemplazar report.txt. Para añadir contenido al final, usa ./report >> report.txt. El operador > trunca el archivo de destino si ya existe antes de iniciar el programa, mientras que >> escribe al final. La sintaxis del shell y los comandos disponibles para compilar pueden variar según la plataforma.

El shell se encarga de abrir el destino redirigido. Si no puede abrirlo, informa del problema y, por lo general, no inicia el programa. El programa no puede detectar ese problema como un error de fopen, porque no abrió el destino. Para guardar los mensajes de diagnóstico por separado, usa ./report > report.txt 2> errors.txt; 2> redirige el descriptor de archivo convencional que se utiliza para stderr.

Redirigir la entrada del programa con <

Lee desde stdin cuando quien ejecuta el programa deba elegir el origen de la entrada. Este programa lee líneas hasta que el archivo redirigido llega al final:

El código y las etiquetas o salidas visibles de esta sección se mantienen en 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;
}

Compílalo como copy-input y luego ejecuta ./copy-input < input.txt. fgets lee como máximo un carácter menos que la capacidad del búfer, añade un carácter nulo de terminación y conserva el salto de línea si alcanza a leerlo. Por eso, una línea larga puede devolverse en varias partes. Después del bucle, comprueba ferror para distinguir un error de lectura del fin de archivo normal. El comportamiento del ejemplo se deriva de las operaciones de flujo de C que se muestran; aquí no se proporciona una salida observada.

Redirigir flujos estándar dentro de un programa C

Cuando el propio programa debe elegir el destino, freopen puede volver a abrir un flujo estándar. Recibe una ruta, un modo como "w" o "a" y el flujo que se volverá a abrir. Por ejemplo, freopen("run.log", "a", stdout) dirige la salida estándar posterior al final de run.log. Antes de escribir, comprueba el valor que devuelve: si falla la reapertura, devuelve NULL. Esto cambia el flujo del proceso; fopen, en cambio, proporciona otro flujo y deja stdout intacto.

Usa esta opción cuando la redirección forme parte del comportamiento del propio programa. Si quien ejecuta el programa debe elegir el destino, deja stdout sin cambios y usa > o >>. freopen forma parte del estándar de C, pero los detalles de cómo se reabre un flujo después de un fallo pueden depender de la implementación. Trata el resultado NULL como un error y no sigas como si la redirección hubiera funcionado.

Gestionar errores y elegir el enfoque adecuado

Comprueba todas las operaciones que puedan fallar. Verifica fopen y freopen antes de usar el flujo que devuelven; comprueba si funciones de salida como fprintf o fputs fallan, y verifica fclose cuando sea importante confirmar que la salida almacenada en búfer llegó al archivo. En los bucles de entrada, un resultado NULL de fgets puede indicar el fin de archivo o un error de lectura; consulta ferror para distinguirlos. perror puede mostrar un mensaje del sistema operativo correspondiente a un fallo asociado con el valor actual de errno.

No determines el tamaño de un búfer de línea según la longitud en bytes que informa un archivo: la entrada puede venir de una tubería o una terminal, y una línea puede superar la capacidad elegida. Un búfer fijo y llamadas repetidas a fgets son adecuados si se pueden procesar los datos por partes. Para leer una línea lógica de longitud arbitraria, amplía el búfer a medida que llegan las partes y comprueba los límites de asignación y de las operaciones aritméticas; otra opción es usar una función específica de la plataforma y explicar sus límites de portabilidad.

Elige la redirección del shell para conectar los flujos estándar durante una ejecución, fopen para manejar un archivo adicional desde C y freopen cuando el propio programa deba reemplazar un flujo estándar. Mantén los mensajes de diagnóstico en stderr cuando redirijas la salida normal y comprueba los fallos en la capa que realiza la operación.