Jak mogę obliczyć rozmiar pliku w bajtach?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
nie FILE* file
? -1
Jak mogę obliczyć rozmiar pliku w bajtach?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
nie FILE* file
? -1
Odpowiedzi:
Na podstawie kodu 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;
}
Zmiany:
const char
.struct stat
definicję, w której brakowało nazwy zmiennej.-1
w przypadku błędu zamiast 0
, co byłoby niejednoznaczne dla pustego pliku. off_t
jest typem ze znakiem, więc jest to możliwe.Jeśli chcesz fsize()
wydrukować komunikat o błędzie, możesz użyć tego:
#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;
}
W systemach 32-bitowych należy to skompilować z opcją -D_FILE_OFFSET_BITS=64
, w przeciwnym razie off_t
będą przechowywane tylko wartości do 2 GB. Szczegółowe informacje można znaleźć w sekcji „Korzystanie z LFS” w dokumencie Obsługa dużych plików w systemie Linux .
fseek
+ ftell
zgodnie z propozycją Dereka.
fseek
+ ftell
zgodnie z propozycją Dereka. Nie C Standardowy wyraźnie stanowi, że fseek()
aby SEEK_END
na plik binarny jest niezdefiniowane zachowanie. 7.19.9.2 fseek
Funkcja ... Strumień binarny nie musi w znaczący sposób obsługiwać fseek
wywołań o wartości pochodzeniaSEEK_END
i, jak wspomniano poniżej, z przypisu 234 na str. 267 połączonego C standardowa, która specyficznie etykiet fseek
do SEEK_END
w binarnego strumienia niezdefiniowana zachowanie. .
Nie używaj int
. Pliki o rozmiarze ponad 2 gigabajtów są obecnie powszechne jako brud
Nie używaj unsigned int
. Pliki o rozmiarze powyżej 4 gigabajtów są powszechne jako nieco mniej powszechny brud
IIRC biblioteka standardowa definiuje off_t
jako 64-bitową liczbę całkowitą bez znaku, której każdy powinien używać. Możemy przedefiniować to na 128 bitów w ciągu kilku lat, kiedy zaczniemy trzymać w pobliżu 16 eksabajtów.
Jeśli korzystasz z systemu Windows, powinieneś użyć GetFileSizeEx - w rzeczywistości używa on 64-bitowej liczby całkowitej ze znakiem, więc zaczną napotykać problemy z 8 plikami eksabajtowymi. Głupi Microsoft! :-)
Rozwiązanie Matta powinno działać, z tym wyjątkiem, że jest to C ++ zamiast C, a początkowe polecenie tell nie powinno być konieczne.
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;
}
Naprawiono też aparat ortodontyczny. ;)
Aktualizacja: to naprawdę nie jest najlepsze rozwiązanie. Jest ograniczony do plików 4 GB w systemie Windows i prawdopodobnie działa wolniej niż zwykłe wywołanie specyficzne dla platformy, takie jak GetFileSizeEx
lub stat64
.
long int
z ftell()
. (unsigned long)
rzucanie nie poprawia zasięgu, który jest już ograniczony przez funkcję. ftell()
zwraca -1 w przypadku błędu i to zostaje zaciemnione przy rzutowaniu. Zaproponuj fsize()
zwrot tego samego typu coftell()
.
** Nie rób tego ( dlaczego? ):
Cytując standardowy dokument C99, który znalazłem online: „Ustawienie wskaźnika pozycji pliku na koniec pliku, tak jak w przypadku
fseek(file, 0, SEEK_END)
, ma niezdefiniowane zachowanie dla strumienia binarnego (z powodu możliwych końcowych znaków zerowych) lub dowolnego strumienia z kodowaniem zależnym od stanu to z pewnością nie kończy się w początkowym stanie zmiany. **
Zmień definicję na int, aby można było przesyłać komunikaty o błędach, a następnie użyj fseek()
i, ftell()
aby określić rozmiar pliku.
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
i ftello
(lub fseek
i ftell
jeśli utkniesz bez poprzedniego i zadowolony z ograniczeniami rozmiary plików można pracować z) jest poprawny sposób określenia długości pliku. stat
rozwiązania oparte na systemie nie działają na wielu "plikach" (takich jak urządzenia blokowe) i nie są przenośne do systemów innych niż POSIX-ish.
Standard POSIX ma własną metodę uzyskiwania rozmiaru pliku.
Dołącz sys/stat.h
nagłówek, aby użyć funkcji.
stat(3)
.st_size
nieruchomość.Uwaga : ogranicza rozmiar do 4GB
. Jeśli nie jest to Fat32
system plików, użyj wersji 64-bitowej!
#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. bezpośrednio nie zapewnia drogę do określenia długości pliku.
Będziemy musieli użyć naszego umysłu. Na razie użyjemy metody wyszukiwania!
#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);
}
Jeśli plik to
stdin
lub potok. POSIX, ANSI C nie będzie działać.
Zwróci,0
jeśli plik jest potokiem lubstdin
.Opinia : Zamiast tego powinieneś użyć standardu POSIX . Ponieważ ma obsługę 64-bitową.
struct _stat64
i __stat64()
dla _Windows.
A jeśli tworzysz aplikację dla Windows, użyj GetFileSizeEx API, ponieważ I / O pliku CRT jest niechlujne, szczególnie przy określaniu długości pliku, ze względu na osobliwości reprezentacji plików na różnych systemach;)
Jeśli nie masz nic przeciwko korzystaniu z biblioteki 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;
}
Szybkie wyszukiwanie w Google znalazło metodę wykorzystującą fseek i ftell oraz wątek z tym pytaniem z odpowiedziami, że nie można tego zrobić w C w inny sposób.
Możesz użyć biblioteki przenośności, takiej jak NSPR (biblioteka, która obsługuje przeglądarkę Firefox) lub sprawdzić jej implementację (raczej włochata).
Użyłem tego zestawu kodu, aby znaleźć długość pliku.
//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);
Spróbuj tego --
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
To, co to robi, to najpierw szukanie do końca pliku; następnie zgłoś, gdzie znajduje się wskaźnik pliku. Na koniec (jest to opcjonalne) przewija się z powrotem do początku pliku. Zwróć na to uwagęfp
powinien to być strumień binarny.
file_size zawiera liczbę bajtów, które zawiera plik. Zwróć uwagę, że ponieważ (według climits.h) typ long unsigned jest ograniczony do 4294967295 bajtów (4 gigabajty), musisz znaleźć inny typ zmiennej, jeśli masz do czynienia z plikami większymi niż to.
ftell
nie zwraca wartości reprezentującej liczbę bajtów, które można odczytać z pliku.
Mam funkcję, która działa dobrze tylko z stdio.h
. Bardzo mi się podoba i działa bardzo dobrze i jest dość zwięzły:
size_t fsize(FILE *File) {
size_t FSZ;
fseek(File, 0, 2);
FSZ = ftell(File);
rewind(File);
return FSZ;
}
Oto prosta i przejrzysta funkcja, która zwraca rozmiar pliku.
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
}
Możesz otworzyć plik, przejść do przesunięcia 0 względem dołu pliku za pomocą
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
wartość zwracana przez fseek to rozmiar pliku.
Długo nie kodowałem w C, ale myślę, że powinno działać.
Patrząc na pytanie, ftell
można łatwo uzyskać liczbę bajtów.
long size = ftell(FILENAME);
printf("total size is %ld bytes",size);
ftell
oczekuje deskryptora pliku, a nie nazwy pliku jako argumentu.
ftell
nie oczekuje deskryptora pliku, oczekuje FILE*
zamiast tego. Najpierw zobacz stronę podręcznika!
fseek()
najpierw do wyszukania końca pliku, a także ftell()
oczekuje , że FILE *
nie ma ciągu! Dobrze by było, gdybyś uściślił swoją odpowiedź.