Você precisará usar uma função de biblioteca para recuperar os detalhes de um arquivo. Como o C é completamente independente da plataforma, você precisará nos informar para qual plataforma / sistema operacional você está desenvolvendo!
Chris Roberts
Por char* fileque não FILE* file? -1
Oscar Oscar
-1 porque as funções de arquivo devem aceitar descritores de arquivo e não caminhos de arquivo
Senhor Oscar
Respostas:
144
Com base no código do NilObject:
#include<sys/stat.h>#include<sys/types.h>off_t fsize(constchar*filename){struct stat st;if(stat(filename,&st)==0)return st.st_size;return-1;}
Alterar:
Tornou o argumento do nome do arquivo a const char.
Corrigida a struct statdefinição, na qual faltava o nome da variável.
Retorna -1com 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(constchar*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.
Isso é específico para Linux / Unix - provavelmente vale a pena apontar isso, pois a pergunta não especificou um sistema operacional.
Drew Hall
1
Você provavelmente pode alterar o tipo de retorno para ssize_t e converter o tamanho de off_t sem nenhum problema. Parece fazer mais sentido usar um ssize_t :-) (Não deve ser confundida com size_t que é não assinado e não pode ser usada para indicar erro.)
Ted Percival
1
Para um código mais portátil, use fseek+ ftellconforme proposto por Derek.
Ciro Santilli #
9
Para um código mais portátil, use fseek+ ftellconforme proposto por Derek. Não. O Padrão C especifica especificamente que fseek()para SEEK_ENDum arquivo binário é um comportamento indefinido. 7.19.9.2 A fseekfunção ... Um fluxo binário não precisa oferecer suporte significativo a fseekchamadas 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 fseekpara SEEK_ENDum fluxo binário como comportamento indefinido. .
Andrew Henle
74
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_tcomo 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! :-)
Eu usei compiladores onde off_t é de 32 bits. É verdade que isso ocorre em sistemas embarcados onde arquivos de 4 GB são menos comuns. De qualquer forma, o POSIX também define off64_t e métodos correspondentes para adicionar à confusão.
Aaron Campbell
Eu sempre amo respostas que assumem o Windows e não fazem mais nada além de criticar a pergunta. Você poderia adicionar algo compatível com POSIX?
SS Anne
1
@ JL2210, a resposta aceita de Ted Percival mostra uma solução compatível com posix, então não vejo sentido em repetir o óbvio. Eu (e 70 outros) pensamos que adicionar a observação sobre o Windows e não usar números inteiros assinados de 32 bits para representar o tamanho dos arquivos era um valor agregado. Cheers
Orion Edwards
30
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.
unsignedlong fsize(char* file){FILE* f = fopen(file,"r");
fseek(f,0, SEEK_END);unsignedlong len =(unsignedlong)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 GetFileSizeExou stat64.
Sim você deveria. No entanto, a menos que haja uma razão realmente convincente para não escrever específica da plataforma, você provavelmente deve usar apenas uma chamada específica da plataforma, em vez do padrão aberto / procurar-final / contar / fechar.
Derek Parque
1
Desculpe a resposta tardia, mas estou tendo um grande problema aqui. Isso faz o aplicativo travar ao acessar arquivos restritos (como protegido por senha ou arquivos do sistema). Existe uma maneira de solicitar uma senha ao usuário quando necessário?
23413 Justin
@ Justin, você provavelmente deve abrir uma nova pergunta especificamente sobre o problema que está enfrentando e fornecer detalhes sobre a plataforma em que está, como está acessando os arquivos e qual é o comportamento.
Derek Parque
1
C99 e C11 retornam long intde 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().
chux - Reinstala Monica
Concordo. O elenco deveria combinar com o protótipo original da questão. Não me lembro por que o transformei em sem assinatura por muito tempo, em vez de sem assinatura.
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.
@mezhaka: Esse relatório do CERT está simplesmente errado. fseekoe ftello(ou fseeke ftellse 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. statAs 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.
R .. GitHub Pare de ajudar o gelo
1
Esta é a única maneira de obter o tamanho do arquivo em muitos sistemas não POSIX (como o meu mbed muito minimalista)
Earlz
9
POSIX
O padrão POSIX possui seu próprio método para obter o tamanho do arquivo.
Inclua o sys/stat.hcabeçalho para usar a função.
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);}
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!
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;)
Esse não é o padrão C. Faz parte do padrão POSIX, mas não o padrão C.
Derek Parque
3
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 descriptorFILE* i_file;
i_file = fopen(source,"r");//gets a long from the file descriptor for fstatlong f_d = fileno(i_file);struct stat buffer;
fstat(f_d,&buffer);//stores file sizelong file_length = buffer.st_size;
fclose(i_file);
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 fpdeve 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.
Esse é um comportamento indefinido para um fluxo binário e para um fluxo de texto ftellnão retorna um valor representativo do número de bytes que podem ser lidos no arquivo.
Andrew Henle
0
Eu tenho uma função que funciona bem apenas stdio.h. Eu gosto muito e funciona muito bem e é bastante conciso:
ftellespera um descritor de arquivo, não um nome de arquivo, como argumento.
Barmar 30/09/16
@ Barmar, No ftellnão espera um descritor de arquivo, ele espera um FILE*. Veja a página de manual primeiro!
A abordagem está completamente errada. É constante que ftellretornaria 0sempre!
Esta resposta está totalmente errada, pois, por exemplo, você precisa 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.
char* file
que nãoFILE* file
? -1Respostas:
Com base no código do NilObject:
Alterar:
const char
.struct stat
definição, na qual faltava o nome da variável.-1
com erro em vez de0
, 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:Em sistemas de 32 bits, você deve compilar isso com a opção
-D_FILE_OFFSET_BITS=64
, caso contráriooff_t
, manterá valores de até 2 GB. Consulte a seção "Usando o LFS" do Suporte a arquivos grandes no Linux para obter detalhes.fonte
fseek
+ftell
conforme proposto por Derek.fseek
+ftell
conforme proposto por Derek. Não. O Padrão C especifica especificamente quefseek()
paraSEEK_END
um arquivo binário é um comportamento indefinido. 7.19.9.2 Afseek
função ... Um fluxo binário não precisa oferecer suporte significativo afseek
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 especificamentefseek
paraSEEK_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 diaNão use
unsigned int
. Arquivos com mais de 4 gigabytes de tamanho são comuns, como uma sujeira um pouco menos comumIIRC, 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! :-)
fonte
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.
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
oustat64
.fonte
long int
deftell()
.(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. Sugerirfsize()
retornar o mesmo tipo queftell()
.** Não faça isso ( por quê? ):
Altere a definição para int para que as mensagens de erro possam ser transmitidas e use
fseek()
eftell()
para determinar o tamanho do arquivo.fonte
fseeko
eftello
(oufseek
eftell
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.POSIX
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.Sinopse
stat(3)
.st_size
propriedade.Exemplos
Nota : Limita o tamanho a
4GB
. Caso contrárioFat32
, use a versão de 64 bits!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
fseek(3)
.ftell(3)
.Exemplo
fonte
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;)
fonte
Se você está bem com o uso da biblioteca std c:
fonte
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).
fonte
Eu usei esse conjunto de códigos para encontrar o tamanho do arquivo.
fonte
Tente isto -
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.
fonte
ftell
não retorna um valor representativo do número de bytes que podem ser lidos no arquivo.Eu tenho uma função que funciona bem apenas
stdio.h
. Eu gosto muito e funciona muito bem e é bastante conciso:fonte
Aqui está uma função simples e limpa que retorna o tamanho do arquivo.
fonte
Você pode abrir o arquivo, vá para 0 deslocamento relativo na parte inferior do arquivo com
o valor retornado do fseek é o tamanho do arquivo.
Não codifiquei em C por um longo tempo, mas acho que deve funcionar.
fonte
Olhando para a pergunta,
ftell
é fácil obter o número de bytes.fonte
ftell
espera um descritor de arquivo, não um nome de arquivo, como argumento.ftell
não espera um descritor de arquivo, ele espera umFILE*
. Veja a página de manual primeiro!ftell
retornaria0
sempre!fseek()
primeiro usar para procurar o final do arquivo e tambémftell()
espera umaFILE *
, não uma string! Você estaria bem servido para elaborar sua resposta.