Buscar..


Sintaxis

  • #include <stdio.h> / * Incluya esto para usar cualquiera de las siguientes secciones * /
  • FILE * fopen (const char * path, const char * mode); / * Abra una secuencia en el archivo en la ruta con el modo especificado * /
  • FILE * freopen (const char * path, const char * mode, FILE * stream); / * Vuelva a abrir una secuencia existente en el archivo en la ruta con el modo especificado * /
  • int fclose (FILE * stream); / * Cerrar un flujo abierto * /
  • size_t fread (void * ptr, size_t size, size_t nmemb, FILE * stream); / * Lea a la mayoría de los elementos nmemb de bytes de tamaño cada uno del flujo y escríbalos en ptr . Devuelve el número de elementos leídos. * /
  • size_t fwrite (const void * ptr, size_t size, size_t nmemb, FILE * stream); / * Escribir nmiemb elementos de size bytes cada uno de ptr a la corriente. Devuelve el número de elementos escritos. * /
  • int fseek (FILE * stream, offset largo, int whence); / * Establezca el cursor del flujo en offset , relativo al desplazamiento indicado por whence , y devuelve 0 si tuvo éxito. * /
  • largo ftell (FILE * stream); / * Devuelve el desplazamiento de la posición actual del cursor desde el principio de la secuencia. * /
  • rebobinado vacío (secuencia de ARCHIVO *); / * Establece la posición del cursor al principio del archivo. * /
  • int fprintf (FILE * fout, const char * fmt, ...); / * Escribe la cadena de formato printf en fout * /
  • ARCHIVO * stdin; / * Flujo de entrada estándar * /
  • ARCHIVO * stdout; / * Flujo de salida estándar * /
  • ARCHIVO * stderr; / * Corriente de error estándar * /

Parámetros

Parámetro Detalles
modo const char * Una cadena que describe el modo de apertura de la secuencia respaldada por archivos. Ver comentarios para los posibles valores.
de dónde viene Puede ser SEEK_SET para establecer desde el principio del archivo, SEEK_END para establecer desde su final, o SEEK_CUR para establecer en relación con el valor actual del cursor. Nota: SEEK_END no es portátil.

Observaciones

Cadenas de modo:

Las cadenas de modo en fopen() y freopen() pueden ser uno de esos valores:

  • "r" : abre el archivo en modo de solo lectura, con el cursor colocado al principio del archivo.
  • "r+" : abre el archivo en modo de lectura y escritura, con el cursor ajustado al principio del archivo.
  • "w" : abra o cree el archivo en modo de solo escritura, con su contenido truncado a 0 bytes. El cursor se establece al principio del archivo.
  • "w+" : abra o cree el archivo en modo de lectura / escritura, con su contenido truncado a 0 bytes. El cursor se establece al principio del archivo.
  • "a" : abre o crea el archivo en modo de solo escritura, con el cursor colocado al final del archivo.
  • "a+" : abre o crea el archivo en modo de lectura y escritura, con el cursor de lectura configurado al principio del archivo. La salida, sin embargo, siempre se agregará al final del archivo.

Cada uno de estos modos de archivo puede tener una b agregada después de la letra inicial (por ejemplo, "rb" o "a+b" o "ab+" ). La b significa que el archivo debe tratarse como un archivo binario en lugar de un archivo de texto en aquellos sistemas donde hay una diferencia. No hace una diferencia en sistemas similares a Unix; Es importante en los sistemas Windows. (Además, Windows fopen permite una t explícita en lugar de b para indicar 'archivo de texto' y muchas otras opciones específicas de la plataforma).

C11
  • "wx" : crea un archivo de texto en modo de solo escritura. El archivo puede no existir .
  • "wbx" : "wbx" un archivo binario en modo de solo escritura. El archivo puede no existir .

La x , si está presente, debe ser el último carácter en la cadena de modo.

Abrir y escribir al archivo

#include <stdio.h>   /* for perror(), fopen(), fputs() and fclose() */
#include <stdlib.h>  /* for the EXIT_* macros */
 
int main(int argc, char **argv)
{
    int e = EXIT_SUCCESS;

    /* Get path from argument to main else default to output.txt */
    char *path = (argc > 1) ? argv[1] : "output.txt";

    /* Open file for writing and obtain file pointer */
    FILE *file = fopen(path, "w");
    
    /* Print error message and exit if fopen() failed */
    if (!file) 
    {
        perror(path);
        return EXIT_FAILURE;
    }

    /* Writes text to file. Unlike puts(), fputs() does not add a new-line. */
    if (fputs("Output in file.\n", file) == EOF)
    {
        perror(path);
        e = EXIT_FAILURE;
    }

    /* Close file */
    if (fclose(file)) 
    {
        perror(path);
        return EXIT_FAILURE;
    }
    return e;
}

Este programa abre el archivo con el nombre dado en el argumento a main, por defecto a output.txt si no se da ningún argumento. Si ya existe un archivo con el mismo nombre, su contenido se descarta y el archivo se trata como un nuevo archivo vacío. Si los archivos no existen, la llamada fopen() crea.

Si la llamada fopen() falla por algún motivo, devuelve un valor NULL y establece el valor de la variable errno global. Esto significa que el programa puede probar el valor devuelto después de la llamada fopen() y usar perror() si fopen() falla.

Si la llamada fopen() tiene éxito, devuelve un puntero de FILE válido. Este puntero se puede usar para hacer referencia a este archivo hasta que se fclose() .

La función fputs() escribe el texto dado en el archivo abierto, reemplazando cualquier contenido anterior del archivo. De manera similar a fopen() , la función fputs() también establece el valor errno si falla, aunque en este caso la función devuelve EOF para indicar el error (de lo contrario, devuelve un valor no negativo).

La función fclose() cualquier búfer, cierra el archivo y libera la memoria apuntada por FILE * . El valor de retorno indica que se completó tal como lo hace fputs() (aunque devuelve '0' si es exitoso), de nuevo, también establece el valor errno en el caso de un error.

fprintf

Puede usar fprintf en un archivo como lo fprintf en una consola con printf . Por ejemplo, para hacer un seguimiento de las victorias del juego, las pérdidas y los empates que pueda escribir

/* saves wins, losses and, ties */
void savewlt(FILE *fout, int wins, int losses, int ties)
{
    fprintf(fout, "Wins: %d\nTies: %d\nLosses: %d\n", wins, ties, losses);
}

Una nota al margen: algunos sistemas (infame, Windows) no usan lo que la mayoría de los programadores llamarían finales de línea "normales". Mientras que los sistemas similares a UNIX usan \ n para terminar líneas, Windows usa un par de caracteres: \ r (retorno de carro) y \ n (avance de línea). Esta secuencia se llama comúnmente CRLF. Sin embargo, siempre que use C, no necesita preocuparse por estos detalles altamente dependientes de la plataforma. Se requiere el compilador de CA para convertir cada instancia de \ n al final de línea de la plataforma correcta. Entonces, un compilador de Windows convertiría \ n a \ r \ n, pero un compilador de UNIX lo mantendría tal como está.

Proceso de ejecución

#include <stdio.h>

void print_all(FILE *stream)
{
    int c;
    while ((c = getc(stream)) != EOF)
        putchar(c);
}
int main(void)
{
    FILE *stream;

    /* call netstat command. netstat is available for Windows and Linux */
    if ((stream = popen("netstat", "r")) == NULL)
        return 1;
  
    print_all(stream);
    pclose(stream);
    return 0;
}

Este programa ejecuta un proceso ( netstat ) a través de popen() y lee toda la salida estándar del proceso y hace eco de eso a la salida estándar.

Nota: popen() no existe en la biblioteca estándar de C , pero es más bien una parte de POSIX C )

Obtener líneas de un archivo usando getline ()

La biblioteca POSIX C define la función getline() . Esta función asigna un búfer para mantener el contenido de la línea y devuelve la nueva línea, el número de caracteres en la línea y el tamaño del búfer.

Programa de ejemplo que obtiene cada línea de example.txt :

#include <stdlib.h>
#include <stdio.h>  


#define FILENAME "example.txt"

int main(void)
{
  /* Open the file for reading */
  char *line_buf = NULL;
  size_t line_buf_size = 0;
  int line_count = 0;
  ssize_t line_size;
  FILE *fp = fopen(FILENAME, "r");
  if (!fp)
  {
    fprintf(stderr, "Error opening file '%s'\n", FILENAME);
    return EXIT_FAILURE;
  }

  /* Get the first line of the file. */
  line_size = getline(&line_buf, &line_buf_size, fp);

  /* Loop through until we are done with the file. */
  while (line_size >= 0)
  {
    /* Increment our line count */
    line_count++;

    /* Show the line details */
    printf("line[%06d]: chars=%06zd, buf size=%06zu, contents: %s", line_count,
        line_size, line_buf_size, line_buf);

    /* Get the next line */
    line_size = getline(&line_buf, &line_buf_size, fp);
  }

  /* Free the allocated line buffer */
  free(line_buf);
  line_buf = NULL;

  /* Close the file now that we are done with it */
  fclose(fp);

  return EXIT_SUCCESS;
}

Ejemplo de archivo de example.txt

This is a file
  which has
multiple lines
    with various indentation,
blank lines



a really long line to show that getline() will reallocate the line buffer if the length of a line is too long to fit in the buffer it has been given,
  and punctuation at the end of the lines.

Salida

line[000001]: chars=000015, buf size=000016, contents: This is a file
line[000002]: chars=000012, buf size=000016, contents:   which has
line[000003]: chars=000015, buf size=000016, contents: multiple lines
line[000004]: chars=000030, buf size=000032, contents:     with various indentation,
line[000005]: chars=000012, buf size=000032, contents: blank lines
line[000006]: chars=000001, buf size=000032, contents: 
line[000007]: chars=000001, buf size=000032, contents: 
line[000008]: chars=000001, buf size=000032, contents: 
line[000009]: chars=000150, buf size=000160, contents: a really long line to show that getline() will reallocate the line buffer if the length of a line is too long to fit in the buffer it has been given,
line[000010]: chars=000042, buf size=000160, contents:  and punctuation at the end of the lines.
line[000011]: chars=000001, buf size=000160, contents: 

En el ejemplo, inicialmente se llama a getline() sin un búfer asignado. Durante esta primera llamada, getline() asigna un búfer, lee la primera línea y coloca el contenido de la línea en el nuevo búfer. En las llamadas subsiguientes, getline() actualiza el mismo búfer y solo reasigna el búfer cuando ya no es lo suficientemente grande como para que quepa toda la línea. El búfer temporal se libera cuando terminamos con el archivo.

Otra opción es getdelim() . Esto es lo mismo que getline() excepto que especifique el carácter de final de línea. Esto solo es necesario si el último carácter de la línea para su tipo de archivo no es '\ n'. getline() funciona incluso con archivos de texto de Windows porque con la línea multibyte el final ( "\r\n") '\ n'` sigue siendo el último carácter de la línea.

Ejemplo de implementación de getline()

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>


#if !(defined _POSIX_C_SOURCE)
typedef long int ssize_t;
#endif

/* Only include our version of getline() if the POSIX version isn't available. */

#if !(defined _POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L

#if !(defined SSIZE_MAX)
#define SSIZE_MAX (SIZE_MAX >> 1)
#endif

ssize_t getline(char **pline_buf, size_t *pn, FILE *fin)
{
  const size_t INITALLOC = 16;
  const size_t ALLOCSTEP = 16;
  size_t num_read = 0;

  /* First check that none of our input pointers are NULL. */
  if ((NULL == pline_buf) || (NULL == pn) || (NULL == fin))
  {
    errno = EINVAL;
    return -1;
  }

  /* If output buffer is NULL, then allocate a buffer. */
  if (NULL == *pline_buf)
  {
    *pline_buf = malloc(INITALLOC);
    if (NULL == *pline_buf)
    {
      /* Can't allocate memory. */
      return -1;
    }
    else
    {
      /* Note how big the buffer is at this time. */
      *pn = INITALLOC;
    }
  }

  /* Step through the file, pulling characters until either a newline or EOF. */

  {
    int c;
    while (EOF != (c = getc(fin)))
    {
      /* Note we read a character. */
      num_read++;

      /* Reallocate the buffer if we need more room */
      if (num_read >= *pn)
      {
        size_t n_realloc = *pn + ALLOCSTEP;
        char * tmp = realloc(*pline_buf, n_realloc + 1); /* +1 for the trailing NUL. */
        if (NULL != tmp)
        {
          /* Use the new buffer and note the new buffer size. */
          *pline_buf = tmp;
          *pn = n_realloc;
        }
        else
        {
          /* Exit with error and let the caller free the buffer. */
          return -1;
        }

        /* Test for overflow. */
        if (SSIZE_MAX < *pn)
        {
          errno = ERANGE;
          return -1;
        }
      }

      /* Add the character to the buffer. */
      (*pline_buf)[num_read - 1] = (char) c;

      /* Break from the loop if we hit the ending character. */
      if (c == '\n')
      {
        break;
      }
    }

    /* Note if we hit EOF. */
    if (EOF == c)
    {
      errno = 0;
      return -1;
    }
  }

  /* Terminate the string by suffixing NUL. */
  (*pline_buf)[num_read] = '\0';

  return (ssize_t) num_read;
}

#endif

Abrir y escribir en un archivo binario

#include <stdlib.h>
#include <stdio.h>


int main(void)
{
   result = EXIT_SUCCESS;

   char file_name[] = "outbut.bin";
   char str[] = "This is a binary file example";
   FILE * fp = fopen(file_name, "wb");
   
   if (fp == NULL)  /* If an error occurs during the file creation */
   {
     result = EXIT_FAILURE;
     fprintf(stderr, "fopen() failed for '%s'\n", file_name);
   }
   else
   {
     size_t element_size = sizeof *str;
     size_t elements_to_write = sizeof str;

     /* Writes str (_including_ the NUL-terminator) to the binary file. */
     size_t elements_written = fwrite(str, element_size, elements_to_write, fp); 
     if (elements_written != elements_to_write)
     {
       result = EXIT_FAILURE;
       /* This works for >=c99 only, else the z length modifier is unknown. */
       fprintf(stderr, "fwrite() failed: wrote only %zu out of %zu elements.\n", 
         elements_written, elements_to_write);
       /* Use this for <c99: *
       fprintf(stderr, "fwrite() failed: wrote only %lu out of %lu elements.\n", 
         (unsigned long) elements_written, (unsigned long) elements_to_write);
        */
     }

     fclose(fp);
   }

   return result;
}

Este programa crea y escribe texto en forma binaria a través de la función fwrite en el archivo output.bin .

Si ya existe un archivo con el mismo nombre, su contenido se descarta y el archivo se trata como un nuevo archivo vacío.

Un flujo binario es una secuencia ordenada de caracteres que puede grabar datos internos de forma transparente. En este modo, los bytes se escriben entre el programa y el archivo sin ninguna interpretación.

Para escribir de forma portátil números enteros, se debe saber si el formato de archivo los espera en formato big o little-endian, y el tamaño (generalmente 16, 32 o 64 bits). El desplazamiento de bits y el enmascaramiento se pueden usar para escribir los bytes en el orden correcto. No se garantiza que los enteros en C tengan representación de complemento a dos (aunque casi todas las implementaciones sí). Afortunadamente, una conversión a unsigned está garantizada para utilizar dos complementos. El código para escribir un entero con signo en un archivo binario es, por lo tanto, un poco sorprendente.

/* write a 16-bit little endian integer */
int fput16le(int x, FILE *fp)
{
    unsigned int rep = x;
    int e1, e2;

    e1 = fputc(rep & 0xFF, fp);
    e2 = fputc((rep >> 8) & 0xFF, fp);

    if(e1 == EOF || e2 == EOF)
        return EOF;
    return 0;  
}

Las otras funciones siguen el mismo patrón con modificaciones menores para el tamaño y el orden de los bytes.

fscanf ()

Digamos que tenemos un archivo de texto y queremos leer todas las palabras en ese archivo para cumplir con algunos requisitos.

archivo.txt :

This is just
a test file
to be used by fscanf()

Esta es la función principal:

#include <stdlib.h>
#include <stdio.h>

void printAllWords(FILE *);

int main(void)
{
  FILE *fp;

  if ((fp = fopen("file.txt", "r")) == NULL) {
      perror("Error opening file");
      exit(EXIT_FAILURE);
  }

  printAllWords(fp);

  fclose(fp);
  
  return EXIT_SUCCESS;
}

void printAllWords(FILE * fp)
{
    char tmp[20];
    int i = 1;

    while (fscanf(fp, "%19s", tmp) != EOF) {
        printf("Word %d: %s\n", i, tmp);
        i++;
    }
}

La salida será:

Word 1: This 
Word 2: is 
Word 3: just
Word 4: a 
Word 5: test
Word 6: file
Word 7: to
Word 8: be 
Word 9: used
Word 10: by
Word 11: fscanf()

Leer líneas de un archivo

El encabezado stdio.h define la fgets() . Esta función lee una línea de una secuencia y la almacena en una cadena específica. La función deja de leer el texto de la secuencia cuando se leen n - 1 caracteres, se lee el carácter de nueva línea ( '\n' ) o se alcanza el final del archivo (EOF).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 80

int main(int argc, char **argv)
{
    char *path;
    char line[MAX_LINE_LENGTH] = {0};
    unsigned int line_count = 0;
    
    if (argc < 1)
        return EXIT_FAILURE;
    path = argv[1];
    
    /* Open file */
    FILE *file = fopen(path, "r");
    
    if (!file)
    {
        perror(path);
        return EXIT_FAILURE;
    }
    
    /* Get each line until there are none left */
    while (fgets(line, MAX_LINE_LENGTH, file))
    {
        /* Print each line */
        printf("line[%06d]: %s", ++line_count, line);
        
        /* Add a trailing newline to lines that don't already have one */
        if (line[strlen(line) - 1] != '\n')
            printf("\n");
    }
    
    /* Close file */
    if (fclose(file))
    {
        return EXIT_FAILURE;
        perror(path);
    }
}

Llamar al programa con un argumento que es una ruta a un archivo que contiene el siguiente texto:

This is a file
  which has
multiple lines
    with various indentation,
blank lines



a really long line to show that the line will be counted as two lines if the length of a line is too long to fit in the buffer it has been given,
  and punctuation at the end of the lines.

Resultará en el siguiente resultado:

line[000001]: This is a file
line[000002]:   which has
line[000003]: multiple lines
line[000004]:     with various indentation,
line[000005]: blank lines
line[000006]: 
line[000007]: 
line[000008]: 
line[000009]: a really long line to show that the line will be counted as two lines if the le
line[000010]: ngth of a line is too long to fit in the buffer it has been given,
line[000011]:  and punctuation at the end of the lines.
line[000012]: 

Este ejemplo muy simple permite una longitud de línea máxima fija, de modo que las líneas más largas se cuenten efectivamente como dos líneas. La fgets() requiere que el código de llamada proporcione la memoria que se utilizará como destino para la línea que se lee.

POSIX pone a disposición la función getline() que, en su lugar, asigna internamente memoria para ampliar el búfer según sea necesario para una línea de cualquier longitud (siempre que haya suficiente memoria).



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow