¿Cómo puedo obtener el tamaño de un archivo en C? [duplicate]

9 minutos de lectura

[*]
nino

¿Cómo puedo saber el tamaño de un archivo que abrí con una aplicación escrita en C? Me gustaría saber el tamaño, porque quiero poner el contenido del archivo cargado en una cadena, que asigno usando malloc(). solo escribiendo malloc(10000*sizeof(char)); es en mi humilde opinión una mala idea.

  • Tenga en cuenta que sizeof(char) es 1, por definición.

    – Randy Proctor

    29 de octubre de 2009 a las 13:44

  • Sí, pero el compilador de alguna plataforma esotérica podría definir char como 2 bytes, entonces el programa asigna más de lo necesario. Uno nunca puede estar demasiado seguro.

    –Nathan Osman

    5 de enero de 2010 a las 2:50

  • @George un “compilador de plataforma esotérica” ​​donde sizeof(char) != 1 no es un verdadero compilador de C. Incluso si un carácter es de 32 bits, seguirá devolviendo 1.

    – Andrew Flanagan

    6 de diciembre de 2010 a las 17:03

  • @George: El estándar C (y C++) garantiza que sizeof(char)==1. Ver por ejemploparashift.com/c++-faq-lite/intrinsic-types.html#faq-26.1

    – sleske

    8 de febrero de 2011 a las 13:40


  • en realidad prefiero malloc(x*sizeof(char)); para malloc(x); al asignar x caracteres. Sí, siempre compilan lo mismo, pero me gusta la coherencia con otras asignaciones de memoria.

    – forma fundida

    16 de abril de 2011 a las 1:16

avatar de usuario
Rob Walker

Debe buscar hasta el final del archivo y luego solicitar la posición:

fseek(fp, 0L, SEEK_END);
sz = ftell(fp);

A continuación, puede buscar hacia atrás, por ejemplo:

fseek(fp, 0L, SEEK_SET);

o (si busca ir al principio)

rewind(fp);

  • @camh – Gracias hombre. Este comentario resolvió un problema que tenía con un algoritmo de tamaño de archivo. Para el registro, uno abre un archivo en modo binario poniendo una ‘b’ al final de la cadena de modo de fopen.

    – TED

    18 de mayo de 2010 a las 10:42

  • Tú, uh, usa rewind antes de que la gente olvide lo que significa

    – bobobobo

    23 de septiembre de 2011 a las 16:55

  • Devuelve un int firmado, por lo que está limitado a 2 GB. Pero en el lado positivo, su archivo podría tener una longitud negativa de 2 mil millones de bytes, y están preparados para eso.

    – set

    13 de febrero de 2012 a las 21:07

  • length = lseek(fd, 0, SEEK_END)+1;

    – Volodymyr M. Lisivka

    16 de noviembre de 2012 a las 16:24

  • Desde documentación fseek “Se permite que las implementaciones de la biblioteca no admitan SEEK_END de manera significativa (por lo tanto, el código que la usa no tiene una portabilidad estándar real)”.

    – Mika Haarahiltunen

    02/09/2013 a las 10:43

avatar de usuario
greg hewgill

Usando la biblioteca estándar:

Suponiendo que su implementación admita significativamente SEEK_END:

fseek(f, 0, SEEK_END); // seek to end of file
size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
// proceed with allocating memory and reading the file

Linux/POSIX:

Puedes usar stat (si conoce el nombre del archivo), o fstat (si tiene el descriptor de archivo).

Aquí hay un ejemplo para stat:

#include <sys/stat.h>
struct stat st;
stat(filename, &st);
size = st.st_size;

Win32:

Puedes usar ObtenerTamañoArchivo o ObtenerTamañoArchivoEx.

  • Tenga en cuenta que he omitido la verificación de errores en aras de la claridad.

    – Greg Hewgill

    26 de octubre de 2008 a las 21:23

  • No necesita el nombre del archivo; puede usar fstat para eso.

    – Tanktalus

    26 de octubre de 2008 a las 21:24

  • Debe señalar la dirección de la estructura. La segunda línea debería ser: stat(filename, &st);

    – Vlad el Impala

    3 de noviembre de 2009 a las 21:16

  • He omitido la verificación de errores en aras de -ERROR FATAL, SALIENDO.

    -Buttle Butkus

    3 de febrero de 2012 a las 9:55

  • La segunda opción es la única que puede mostrar archivos de más de 2 GB.

    – set

    13 de febrero de 2012 a las 21:52

avatar de usuario
Flautista de Hamelín

Si tiene el descriptor de archivo fstat() devuelve una estructura estadística que contiene el tamaño del archivo.

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

// fd = fileno(f); //if you have a stream (e.g. from fopen), not a file descriptor.
struct stat buf;
fstat(fd, &buf);
off_t size = buf.st_size;

  • Agregue “fd = fileno(f);” si tiene una transmisión (por ejemplo, de fopen), no un descriptor de archivo. Necesita comprobación de errores.

    – ysth

    26 de octubre de 2008 a las 21:24

  • Por supuesto, necesita verificación de errores, eso solo complicaría el ejemplo.

    – Flautista de Hamelín

    26 de octubre de 2008 a las 21:28

  • esta es, en mi opinión, la mejor respuesta real, y creo que todos tenemos nuestras ruedas de entrenamiento apagadas en su mayor parte en C, ¿realmente necesitamos la verificación de errores y otro código innecesario en nuestros ejemplos? el de ellos, no hagamos lo mismo, sino que digamos al final ‘asegúrese de agregar la verificación de errores’ y terminemos con eso.

    – osirisgothra

    7 de noviembre de 2013 a las 16:45


  • MUCHOS de los usuarios de SO son estudiantes de C, no maestros anteriores. Por lo tanto, el código dado en las respuestas debe mostrar la verificación de errores, para que el estudiante aprenda la forma correcta de codificar.

    – usuario3629249

    23/02/2015 a las 18:30

  • existe el detalle de que (f)stat() devuelve los bytes totales de asignación de bloques mientras que la secuencia fseek() / ftell() devuelve el número de bytes antes de que se encuentre EOF.

    – usuario3629249

    23 de febrero de 2015 a las 18:32

Cómo utilizar busco/buscar/estadística/fstat para obtener tamaño de archivo?

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

void
fseek_filesize(const char *filename)
{
    FILE *fp = NULL;
    long off;

    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        printf("failed to fopen %s\n", filename);
        exit(EXIT_FAILURE);
    }

    if (fseek(fp, 0, SEEK_END) == -1)
    {
        printf("failed to fseek %s\n", filename);
        exit(EXIT_FAILURE);
    }

    off = ftell(fp);
    if (off == -1)
    {
        printf("failed to ftell %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] fseek_filesize - file: %s, size: %ld\n", filename, off);

    if (fclose(fp) != 0)
    {
        printf("failed to fclose %s\n", filename);
        exit(EXIT_FAILURE);
    }
}

void
fstat_filesize(const char *filename)
{
    int fd;
    struct stat statbuf;

    fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
    if (fd == -1)
    {
        printf("failed to open %s\n", filename);
        exit(EXIT_FAILURE);
    }

    if (fstat(fd, &statbuf) == -1)
    {
        printf("failed to fstat %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] fstat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);

    if (close(fd) == -1)
    {
        printf("failed to fclose %s\n", filename);
        exit(EXIT_FAILURE);
    }
}

void
stat_filesize(const char *filename)
{
    struct stat statbuf;

    if (stat(filename, &statbuf) == -1)
    {
        printf("failed to stat %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] stat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);

}

void
seek_filesize(const char *filename)
{
    int fd;
    off_t off;

    if (filename == NULL)
    {
        printf("invalid filename\n");
        exit(EXIT_FAILURE);
    }

    fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
    if (fd == -1)
    {
        printf("failed to open %s\n", filename);
        exit(EXIT_FAILURE);
    }

    off = lseek(fd, 0, SEEK_END);
    if (off == -1)
    {
        printf("failed to lseek %s\n", filename);
        exit(EXIT_FAILURE);
    }

    printf("[*] seek_filesize - file: %s, size: %lld\n", filename, (long long) off);

    if (close(fd) == -1)
    {
        printf("failed to close %s\n", filename);
        exit(EXIT_FAILURE);
    }
}

int
main(int argc, const char *argv[])
{
    int i;

    if (argc < 2)
    {
        printf("%s <file1> <file2>...\n", argv[0]);
        exit(0);
    }

    for(i = 1; i < argc; i++)
    {
        seek_filesize(argv[i]);
        stat_filesize(argv[i]);
        fstat_filesize(argv[i]);
        fseek_filesize(argv[i]);
    }

    return 0;
}

avatar de usuario
ben combee

Si está en Linux, considere seriamente simplemente usar el g_file_get_contents función de glib. Maneja todo el código para cargar un archivo, asignar memoria y manejar errores.

  • Si estás en Linux y quiero tener una dependencia de glib, eso es.

    – JesperE

    26 de octubre de 2008 a las 22:25

  • No es un problema tan malo, ya que ahora las aplicaciones GTK y KDE utilizan glib. También está disponible en Mac OS X y Windows, pero no es tan estándar allí.

    – Ben Combee

    29 de octubre de 2008 a las 19:23

  • ¿Pero no es glib una biblioteca de C++? La pregunta estipulada C

    – Dave Appleton

    21 de junio de 2013 a las 9:54

  • @DaveAppleton: No, glib es en gran medida una biblioteca C simple, no C ++.

    – Nate CK

    20 de febrero de 2014 a las 4:13

  • @BenCombee glib no está en Android, la última vez que lo comprobé.

    – Wyatt Ward

    1 de mayo de 2017 a las 4:40

avatar de usuario
condez

Terminé haciendo un breve y dulce fsize función (nota, sin comprobación de errores)

int fsize(FILE *fp){
    int prev=ftell(fp);
    fseek(fp, 0L, SEEK_END);
    int sz=ftell(fp);
    fseek(fp,prev,SEEK_SET); //go back to where we were
    return sz;
}

Es un poco tonto que la biblioteca C estándar no tenga esa función, pero puedo ver por qué sería difícil ya que no todos los “archivos” tienen un tamaño (por ejemplo /dev/null)

  • Si estás en Linux y quiero tener una dependencia de glib, eso es.

    – JesperE

    26 de octubre de 2008 a las 22:25

  • No es un problema tan malo, ya que ahora las aplicaciones GTK y KDE utilizan glib. También está disponible en Mac OS X y Windows, pero no es tan estándar allí.

    – Ben Combee

    29 de octubre de 2008 a las 19:23

  • ¿Pero no es glib una biblioteca de C++? La pregunta estipulada C

    – Dave Appleton

    21 de junio de 2013 a las 9:54

  • @DaveAppleton: No, glib es en gran medida una biblioteca C simple, no C ++.

    – Nate CK

    20 de febrero de 2014 a las 4:13

  • @BenCombee glib no está en Android, la última vez que lo comprobé.

    – Wyatt Ward

    1 de mayo de 2017 a las 4:40

avatar de usuario
ensambladorplan9

#include <stdio.h>

#define MAXNUMBER 1024

int main()
{
    int i;
    char a[MAXNUMBER];

    FILE *fp = popen("du -b  /bin/bash", "r");

    while((a[i++] = getc(fp))!= 9)
        ;

    a[i] ='\0';

    printf(" a is %s\n", a);

    pclose(fp);
    return 0;
}  

HTH

  • Esta solución es innecesariamente compleja e ineficiente. No es necesario ejecutar un comando y analizar su salida, como lo aclaran las respuestas anteriores.

    – brandizzi

    12 de marzo de 2011 a las 15:16

  • Además, esta es una solución solo para Linux

    – bobobobo

    23 de septiembre de 2011 a las 16:57

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad