¿Cómo puedo calcular el tamaño de un archivo, en bytes?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, por qué no FILE* file
? -1
¿Cómo puedo calcular el tamaño de un archivo, en bytes?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, por qué no FILE* file
? -1
Respuestas:
Basado en el código de NilObject:
#include <sys/stat.h>
#include <sys/types.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
return -1;
}
Cambios:
const char
.struct stat
definición, a la que le faltaba el nombre de la variable.-1
por error en lugar de 0
, lo que sería ambiguo para un archivo vacío. off_t
es un tipo con signo, por lo que esto es posible.Si desea fsize()
imprimir un mensaje de error, puede usar esto:
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
fprintf(stderr, "Cannot determine size of %s: %s\n",
filename, strerror(errno));
return -1;
}
En sistemas de 32 bits, debe compilar esto con la opción -D_FILE_OFFSET_BITS=64
; de lo contrario off_t
, solo tendrá valores de hasta 2 GB. Consulte la sección "Uso de LFS" de Soporte de archivos grandes en Linux para más detalles.
fseek
+ ftell
según lo propuesto por Derek.
fseek
+ ftell
según lo propuesto por Derek. No. El C estándar establece específicamente que fseek()
a SEEK_END
en un archivo binario es un comportamiento indefinido. 7.19.9.2 La fseek
función ... Una secuencia binaria no necesita admitir significativamente fseek
llamadas con un valor de origen deSEEK_END
, y como se indica a continuación, que es de la nota 234 en la p. 267 de la C Standard vinculado, y que expresamente etiquetas fseek
a SEEK_END
en una corriente binaria como un comportamiento indefinido. .
No utilice int
. Los archivos de más de 2 gigabytes de tamaño son comunes en la actualidad.
No utilice unsigned int
. Los archivos de más de 4 gigabytes de tamaño son comunes como algo de tierra un poco menos común
IIRC, la biblioteca estándar, se define off_t
como un entero de 64 bits sin signo, que es lo que todos deberían usar. Podemos redefinir que sean 128 bits en unos pocos años cuando comencemos a tener 16 archivos exabyte dando vueltas.
Si está en Windows, debe usar GetFileSizeEx ; en realidad usa un entero de 64 bits con signo, por lo que comenzarán a resolver problemas con 8 archivos exabyte. Tonto de Microsoft! :-)
La solución de Matt debería funcionar, excepto que es C ++ en lugar de C, y la información inicial no debería ser necesaria.
unsigned long fsize(char* file)
{
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(f);
fclose(f);
return len;
}
También arregló su abrazadera para usted. ;)
Actualización: esta no es realmente la mejor solución. Está limitado a archivos de 4GB en Windows y es probable que sea más lento que usar una llamada específica de la plataforma como GetFileSizeEx
o stat64
.
long int
de ftell()
. (unsigned long)
el lanzamiento no mejora el rango ya que está limitado por la función. ftell()
devuelve -1 por error y eso se ofusca con el elenco. Sugerir fsize()
devolver el mismo tipo que ftell()
.
** No hagas esto ( ¿por qué? ):
Citando el documento estándar C99 que encontré en línea: "Establecer el indicador de posición del archivo al final del archivo, como con
fseek(file, 0, SEEK_END)
, tiene un comportamiento indefinido para una secuencia binaria (debido a posibles caracteres nulos finales) o para cualquier secuencia con codificación dependiente del estado que seguramente no termina en el estado de cambio inicial. **
Cambie la definición a int para que se puedan transmitir mensajes de error, y luego use fseek()
y ftell()
para determinar el tamaño del archivo.
int fsize(char* file) {
int size;
FILE* fh;
fh = fopen(file, "rb"); //binary mode
if(fh != NULL){
if( fseek(fh, 0, SEEK_END) ){
fclose(fh);
return -1;
}
size = ftell(fh);
fclose(fh);
return size;
}
return -1; //error
}
fseeko
y ftello
(o fseek
y ftell
si le pegan sin la primera y feliz con límites en el tamaño de los archivos se puede trabajar con) es la forma correcta para determinar la longitud de un archivo. stat
Las soluciones basadas en sistemas no funcionan en muchos "archivos" (como dispositivos de bloque) y no son portátiles para sistemas que no son POSIX-ish.
El estándar POSIX tiene su propio método para obtener el tamaño del archivo.
Incluya el sys/stat.h
encabezado para usar la función.
stat(3)
.st_size
propiedad.Nota : limita el tamaño a 4GB
. Si no es un Fat32
sistema de archivos, ¡use la versión de 64 bits!
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat info;
stat(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat64 info;
stat64(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
El ANSI C no proporciona directamente la forma de determinar la longitud del archivo.
Tendremos que usar nuestra mente. Por ahora, utilizaremos el enfoque de búsqueda.
#include <stdio.h>
int main(int argc, char** argv)
{
FILE* fp = fopen(argv[1]);
int f_size;
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
rewind(fp); // to back to start again
printf("%s: size=%ld", (unsigned long)f_size);
}
Si el archivo es
stdin
o una tubería. POSIX, ANSI C no funcionará.
Volverá0
si el archivo es una tubería ostdin
.Opinión : en su lugar, debe usar el estándar POSIX . Porque tiene soporte de 64 bits.
struct _stat64
y __stat64()
para _Windows.
Y si está creando una aplicación de Windows, use la API GetFileSizeEx ya que la E / S del archivo CRT es desordenada, especialmente para determinar la longitud del archivo, debido a peculiaridades en las representaciones de archivos en diferentes sistemas;)
Si está bien con el uso de la biblioteca std c:
#include <sys/stat.h>
off_t fsize(char *file) {
struct stat filestat;
if (stat(file, &filestat) == 0) {
return filestat.st_size;
}
return 0;
}
Una búsqueda rápida en Google encontró un método usando fseek y ftell y un hilo con esta pregunta con respuestas que no se puede hacer solo en C de otra manera.
Podría usar una biblioteca de portabilidad como NSPR (la biblioteca que alimenta Firefox) o verificar su implementación (bastante complicada).
Usé este conjunto de código para encontrar la longitud del archivo.
//opens a file with a file descriptor
FILE * i_file;
i_file = fopen(source, "r");
//gets a long from the file descriptor for fstat
long f_d = fileno(i_file);
struct stat buffer;
fstat(f_d, &buffer);
//stores file size
long file_length = buffer.st_size;
fclose(i_file);
Prueba esto --
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
Lo que esto hace es primero, buscar hasta el final del archivo; luego, informe dónde está el puntero del archivo. Por último (esto es opcional), se rebobina al principio del archivo. Tenga en cuenta quefp
debería ser una secuencia binaria.
file_size contiene el número de bytes que contiene el archivo. Tenga en cuenta que dado que (según climits.h) el tipo largo sin signo está limitado a 4294967295 bytes (4 gigabytes) necesitará encontrar un tipo de variable diferente si es probable que maneje archivos más grandes que eso.
ftell
no devuelve un valor representativo del número de bytes que se pueden leer del archivo.
Tengo una función que funciona bien solo con stdio.h
. Me gusta mucho y funciona muy bien y es bastante conciso:
size_t fsize(FILE *File) {
size_t FSZ;
fseek(File, 0, 2);
FSZ = ftell(File);
rewind(File);
return FSZ;
}
Aquí hay una función simple y limpia que devuelve el tamaño del archivo.
long get_file_size(char *path)
{
FILE *fp;
long size = -1;
/* Open file for reading */
fp = fopen(path, "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fp.close();
return
}
Puede abrir el archivo, ir a 0 desplazamiento relativo desde la parte inferior del archivo con
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
El valor devuelto por fseek es el tamaño del archivo.
No codifiqué en C durante mucho tiempo, pero creo que debería funcionar.
Mirando la pregunta, ftell
puede obtener fácilmente el número de bytes.
long size = ftell(FILENAME);
printf("total size is %ld bytes",size);
ftell
espera un descriptor de archivo, no un nombre de archivo, como argumento.
ftell
no espera un descriptor de archivo, espera un FILE*
en su lugar. ¡Vea la página del manual primero!
fseek()
primero para buscar el final del archivo y, además, ftell()
espera una FILE *
, ¡no una cadena! Estarías bien servido para desarrollar tu respuesta.