Como posso descobrir o tamanho de um arquivo, em bytes?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
que não FILE* file
? -1
Como posso descobrir o tamanho de um arquivo, em bytes?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
que não FILE* file
? -1
Respostas:
Com base 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;
}
Alterar:
const char
.struct stat
definição, na qual faltava o nome da variável.-1
com erro em vez de 0
, o que seria ambíguo para um arquivo vazio. off_t
é um tipo assinado, portanto isso é possível.Se você deseja fsize()
imprimir uma mensagem com erro, pode usar o seguinte:
#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
, caso contrário off_t
, manterá valores de até 2 GB. Consulte a seção "Usando o LFS" do Suporte a arquivos grandes no Linux para obter detalhes.
fseek
+ ftell
conforme proposto por Derek.
fseek
+ ftell
conforme proposto por Derek. Não. O Padrão C especifica especificamente que fseek()
para SEEK_END
um arquivo binário é um comportamento indefinido. 7.19.9.2 A fseek
função ... Um fluxo binário não precisa oferecer suporte significativo a fseek
chamadas com um valor deSEEK_END
e, conforme observado abaixo, que é da nota de rodapé 234 na p. 267 do Padrão C vinculado e que rotula especificamente fseek
para SEEK_END
um fluxo binário como comportamento indefinido. .
Não use int
. Arquivos com mais de 2 gigabytes de tamanho são comuns hoje em dia
Não use unsigned int
. Arquivos com mais de 4 gigabytes de tamanho são comuns, como uma sujeira um pouco menos comum
IIRC, a biblioteca padrão define off_t
como um número inteiro de 64 bits não assinado, que é o que todos deveriam usar. Podemos redefinir isso para 128 bits em alguns anos, quando começamos a ter 16 arquivos de exabyte por aí.
Se você estiver no Windows, use GetFileSizeEx - ele realmente usa um número inteiro de 64 bits assinado, para que eles comecem a ter problemas com 8 arquivos de exabyte. Microsoft tolo! :-)
A solução de Matt deve funcionar, exceto que é C ++ em vez de C, e a instruçã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;
}
Corrigido sua chave para você também. ;)
Atualização: Esta não é realmente a melhor solução. É limitado a arquivos de 4 GB no Windows e provavelmente é mais lento do que usar uma chamada específica da plataforma, como GetFileSizeEx
ou stat64
.
long int
de ftell()
. (unsigned long)
a transmissão não melhora o alcance, como já limitado pela função. ftell()
retorne -1 com erro e que sejam ofuscados com o elenco. Sugerir fsize()
retornar o mesmo tipo que ftell()
.
** Não faça isso ( por quê? ):
Citando o documento padrão C99 que eu encontrei on-line: "A configuração do indicador de posição do arquivo como final de arquivo, com
fseek(file, 0, SEEK_END)
comportamento indefinido para um fluxo binário (devido a possíveis caracteres nulos à direita) ou para qualquer fluxo com codificação dependente do estado que certamente não termina no estado de turno inicial. **
Altere a definição para int para que as mensagens de erro possam ser transmitidas e 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
}
fseeko
e ftello
(ou fseek
e ftell
se você está preso sem o primeiro e feliz com limites sobre o tamanho dos arquivos que você pode trabalhar com) são a maneira correta para determinar o comprimento de um arquivo. stat
As soluções baseadas em software não funcionam em muitos "arquivos" (como dispositivos de bloco) e não são portáveis para sistemas não POSIX-ish.
O padrão POSIX possui seu próprio método para obter o tamanho do arquivo.
Inclua o sys/stat.h
cabeçalho para usar a função.
stat(3)
.st_size
propriedade.Nota : Limita o tamanho a 4GB
. Caso contrário Fat32
, 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);
}
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!
#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 é
stdin
ou um tubo. POSIX, ANSI C não funcionará.
Ele retornará0
se o arquivo for um pipe oustdin
.Opinião : você deve usar o padrão POSIX . Porque, ele tem suporte para 64 bits.
struct _stat64
e __stat64()
para _Windows.
E se você estiver criando um aplicativo do Windows, use a API GetFileSizeEx, pois a E / S do arquivo CRT é confusa, especialmente para determinar o tamanho do arquivo, devido a peculiaridades nas representações de arquivos em diferentes sistemas;)
Se você está bem com o uso da 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;
}
Uma pesquisa rápida no Google encontrou um método usando fseek e ftell e um tópico com esta pergunta com respostas que não podem ser feitas apenas em C de outra maneira.
Você pode usar uma biblioteca de portabilidade como o NSPR (a biblioteca que alimenta o Firefox) ou verificar sua implementação (um tanto complicada).
Eu usei esse conjunto de códigos para encontrar o tamanho 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, procure o final do arquivo; em seguida, relate onde está o ponteiro do arquivo. Por fim (isso é 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 climits.h), o tipo longo não assinado é limitado a 4294967295 bytes (4 gigabytes), você precisará encontrar um tipo de variável diferente se for possível lidar com arquivos maiores que isso.
ftell
não retorna um valor representativo do número de bytes que podem ser lidos no arquivo.
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ê pode abrir o arquivo, vá para 0 deslocamento relativo na parte inferior do arquivo com
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
o valor retornado do fseek é o tamanho do arquivo.
Não codifiquei em C por um longo tempo, mas acho que deve funcionar.
Olhando para a pergunta, ftell
é fácil obter o número de bytes.
long size = ftell(FILENAME);
printf("total size is %ld bytes",size);
ftell
espera um descritor de arquivo, não um nome de arquivo, como argumento.
ftell
não espera um descritor de arquivo, ele espera um FILE*
. Veja a página de manual primeiro!
fseek()
primeiro usar para procurar o final do arquivo e também ftell()
espera uma FILE *
, não uma string! Você estaria bem servido para elaborar sua resposta.