manejo - ¿Cómo puedo obtener el tamaño de un archivo en C?
guardar y leer datos en un archivo.txt en c (8)
Usando la biblioteca estándar:
Suponiendo que su implementación sea compatible con 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:
Puede usar stat
(si conoce el nombre de 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:
Puede utilizar GetFileSize o GetFileSizeEx .
Posible duplicado:
¿Cómo determinas el tamaño de un archivo en C?
¿Cómo puedo averiguar el tamaño de un archivo? 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));
En mi opinión, es una mala idea.
¿Cómo usar lseek / fseek / stat / fstat para obtener el 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 == (long)-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 == (off_t)-1)
{
printf("failed to lseek %s/n", filename);
exit(EXIT_FAILURE);
}
printf("[*] seek_filesize - file: %s, size: %lld/n", filename, 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;
}
¿Ha considerado no calcular el tamaño del archivo y simplemente aumentar la matriz si es necesario? Aquí hay un ejemplo (con la verificación de errores omitida):
#define CHUNK 1024
/* Read the contents of a file into a buffer. Return the size of the file
* and set buf to point to a buffer allocated with malloc that contains
* the file contents.
*/
int read_file(FILE *fp, char **buf)
{
int n, np;
char *b, *b2;
n = CHUNK;
np = n;
b = malloc(sizeof(char)*n);
while ((r = fread(b, sizeof(char), CHUNK, fp)) > 0) {
n += r;
if (np - n < CHUNK) {
np *= 2; // buffer is too small, the next read could overflow!
b2 = malloc(np*sizeof(char));
memcpy(b2, b, n * sizeof(char));
free(b);
b = b2;
}
}
*buf = b;
return n;
}
Esto tiene la ventaja de funcionar incluso para transmisiones en las que es imposible obtener el tamaño del archivo (como la entrada estándar).
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);
Si estás en Linux, considera seriamente usar la función g_file_get_contents de glib. Maneja todo el código para cargar un archivo, asignar memoria y manejar errores.
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;
Terminé haciendo una función de fsize
corto y dulce (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 estándar de C no tenga tal 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
)
#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