Como você determina o tamanho de um arquivo em C?
Pergunta
Como posso descobrir o tamanho de um arquivo, em bytes?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
Solução
Baseado no código do 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;
}
Mudanças:
- Tornou o argumento do nome do arquivo um
const char
. - Corrigido o
struct stat
definição, que estava faltando o nome da variável. - Devoluções
-1
por erro em vez de0
, o que seria ambíguo para um arquivo vazio.off_t
é um tipo assinado, então isso é possível.
Se você quiser fsize()
para imprimir uma mensagem de erro, você pode usar isto:
#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;
}
Em sistemas de 32 bits você deve compilar isso com a opção -D_FILE_OFFSET_BITS=64
, de outra forma off_t
armazenará apenas valores de até 2 GB.Veja a seção "Usando LFS" do Suporte a arquivos grandes no Linux para detalhes.
Outras dicas
Não use int
.Arquivos com mais de 2 gigabytes de tamanho são comuns como sujeira atualmente
Não use unsigned int
.Arquivos com mais de 4 gigabytes de tamanho são comuns como alguma sujeira um pouco menos comum
IIRC, a biblioteca padrão define off_t
como um número inteiro não assinado de 64 bits, que é o que todos deveriam usar.Podemos redefinir isso para 128 bits em alguns anos, quando começarmos a ter arquivos de 16 exabytes por aí.
Se você estiver no Windows, você deve usar GetFileSizeEx - na verdade, ele usa um número inteiro assinado de 64 bits, então eles começarão a ter problemas com arquivos de 8 exabytes.Microsoft tola!:-)
A solução de Matt deve funcionar, exceto que é C++ em vez de C, e a informação inicial não deve ser necessária.
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;
}
Consertei seu aparelho para você também.;)
Atualizar:Esta não é realmente a melhor solução.É limitado a arquivos de 4 GB no Windows e provavelmente é mais lento do que apenas usar uma chamada específica da plataforma, como GetFileSizeEx
ou stat64
.
**Não faça isso (por que?):
Citando o documento padrão C99 que encontrei online:"Definir o indicador de posição do arquivo como fim do arquivo, como acontece com fseek(file, 0, SEEK_END), tem comportamento indefinido para um fluxo binário (devido a possíveis caracteres nulos à direita) ou para qualquer fluxo com codificação dependente de estado que não certamente não terminará no estado de mudança inicial.**
Altere a definição para int para que as mensagens de erro possam ser transmitidas e, em seguida, use fseek() e ftell() para determinar o tamanho do arquivo.
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
}
Se você concordar em usar a 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;
}
POSIX
O POSIX standard tem seu próprio método para obter o tamanho do arquivo.
Incluir o sys/stat.h
cabeçalho para usar a função.
Sinopse
- Obtenha estatísticas de arquivos usando
stat(3)
. - Obtenha o
st_size
propriedade.
Exemplos
Observação:Limita o tamanho a 4GB
.Se não Fat32
sistema de arquivos, use a versão 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);
}
ANSI C (padrão)
O ANSI-C não fornece diretamente a maneira de determinar o comprimento do arquivo.
Teremos que usar nossa mente.Por enquanto, usaremos a abordagem de busca!
Sinopse
Exemplo
#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);
}
Se o arquivo for
stdin
ou um cano. POSIX, ANSI C não vai funcionar.
Irá retornar0
se o arquivo for um pipe oustdin
.Opinião:Você deveria usar POSIX padrão em vez disso.Porque tem suporte para 64 bits.
E se você estiver criando um aplicativo do Windows, use o GetFileSizeEx API como E/S de arquivo CRT é confusa, especialmente para determinar o comprimento do arquivo, devido a peculiaridades nas representações de arquivos em diferentes sistemas;)
Uma pesquisa rápida no Google encontrou um método usando fseek e ftell e um tópico com esta pergunta com respostas de que isso não pode ser feito apenas em C de outra maneira.
Você poderia usar uma biblioteca de portabilidade como NSPR (a biblioteca que alimenta o Firefox) ou verifique sua implementação (bastante peludo).
Usei esse conjunto de código para encontrar o comprimento do arquivo.
//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);
Tente isto -
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
O que isso faz é primeiro buscar o final do arquivo;em seguida, informe onde está o ponteiro do arquivo.Por último (opcional), ele volta ao início do arquivo.Observe que fp
deve ser um fluxo binário.
file_size contém o número de bytes que o arquivo contém.Observe que, como (de acordo com clilimits.h) o tipo longo não assinado é limitado a 4294967295 bytes (4 gigabytes), você precisará encontrar um tipo de variável diferente se for provável que lide com arquivos maiores que isso.
Aqui está uma função simples e limpa que retorna o tamanho do arquivo.
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
}
Você precisará usar uma função de biblioteca para recuperar os detalhes de um arquivo.Como C é completamente independente de plataforma, você precisará nos informar para qual plataforma/sistema operacional você está desenvolvendo!
Olhando para a pergunta, ftell
pode facilmente obter o número de bytes.
long size ;
size = ftell(FILENAME);
printf("total size is %ld bytes",size);
Você pode abrir o arquivo, ir para o deslocamento 0 relativo à parte inferior do arquivo com
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
o valor retornado de fseek é o tamanho do arquivo.
Faz muito tempo que não codifico em C, mas acho que deve funcionar.