2012-01-26 11 views
9

Zanim ktoś skarży się na „duplikat”, byłem dość dokładnie sprawdzanie SO, ale nie wydaje się być jeszcze nie czysty odpowiedź, chociaż sprawa wygląda całkiem proste.Get duży rozmiar pliku w C

Szukam przenośnego kodu C, który jest w stanie dostarczyć rozmiar pliku, nawet jeśli taki plik jest większy niż 4 GB.

Zwykła metoda (fseek, ftell) działa dobrze, tak długo, jak plik pozostaje < 2GB. Jest dość dobrze obsługiwany wszędzie, więc staram się znaleźć coś podobnego.

Niestety, zaktualizowane metody (fseeko, ftello) nie są obsługiwane przez wszystkie kompilatory. Na przykład MinGW tęskni za nią (i oczywiście MSVC). Ponadto, niektóre komentarze sprawiają, że wierzę, że nowy typ zwrotu (off_t) niekoniecznie obsługuje rozmiar> 2 GB, może być zależny od niektórych parametrów zewnętrznych, które należy sprawdzić.

Metody jednoznaczne (fseeko64, ftello64) nie są obsługiwane przez MSVC. MS dostarcza ich odpowiednik, _fseeki64 & _ftelli64. To już jest złe, ale staje się gorsze: niektóre konfiguracje Linuksa wydają się źle obsługiwać te funkcje podczas pracy. Na przykład mój Debian Squeeze na PowerPC, używając GCC 4.4, będzie produkował metodę "filesize" za pomocą fseeko64, która zawsze zwraca 0 (gdy działa dobrze dla Ubuntu64). MinGW wydaje się odpowiadać na losowe śmieci powyżej 2GB.

Cóż, jestem trochę pojęcia miarę przenoszenia jest zaniepokojony. A jeśli potrzebuję zrobić garść #if #else, to dlaczego nie pójść od razu do metod specyficznych dla kompilatorów OS &, na przykład GetFileSize() dla MSVC.

+3

Jaka jest Twoja definicja "przenośnego"? Istnieje wiele systemów, które nie mogą nawet otwierać plików. Jeszcze więcej nie może otworzyć plików o rozmiarze ponad 4 GB. –

Odpowiedz

8

Powiedziałeś: nie ma przenośnej metody; gdybym był tobą, po prostu zadzwoniłbym pod numer GetFileSize w systemie Windows i stat w systemie POSIX.

+2

Możesz użyć '_stat64' w Windows, aby kod * sorta * był taki sam. – user7116

+1

@sletterlettervariables: poprawne, chociaż nie wiem, czy każdy kompilator w systemie Windows go implementuje (podczas gdy 'GetFileSize' jest częścią Windows API, więc powinien być zawsze dostępny). –

+0

Interesujące. Spróbuję tego. – Cyan

6
int ch; 
FILE *f = fopen("file_to_analyse", "rb"); 
/* error checking ommited for brevity */ 
unsigned long long filesize = 0; /* or unsigned long for C89 compatability*/ 
while ((ch = fgetc(f)) != EOF) filesize++; 
fclose(f); 
/* error checking ommited for brevity */ 
+2

OK, to jedyny standard zgodny ze standardami, ale mam nadzieję, że jesteś sarkastyczny: czytasz cały plik, prawdopodobnie 2 GB, jeden znak na raz, żeby poznać jego rozmiar (który na bieżących systemach plików jest po prostu atrybutem pliku) jest zwyczajnie głupi ... –

+0

Mam nadzieję, że to żart. – kichik

+2

Och, nie, nie, nie ... proszę powiedz mi, że żartujesz. Z drugiej strony, pytanie dotyczy przenośnego sposobu, a nie skutecznego. To naprawdę przenośny sposób. –

1
#include sys/stat.h 

off_t fsize(const char *filename) { 
    struct stat st; 

    if (stat(filename, &st) == 0) 
     return st.st_size; 

    return -1; 
} 
+0

Może mógłbyś spróbować przeczytać pytanie. –

6

Powinieneś być w stanie wykorzystać stat64 on Linux i _stat64 on Windows, aby uzyskać informacje o rozmiarze pliku dla plików ponad 2 GBs, a obie funkcje są bardzo podobne pod względem zużycia. Można również użyć kilka #define s używać stat64 na Windows zbyt:

#if __WIN32__ 
#define stat64 _stat64 
#endif 

Jednak mimo to powinno działać, należy zauważyć, że rodzina funkcji w systemie Windows _stat jest naprawdę tylko otoki wokół innych funkcji i doda dodatkowe zasoby i czas narzut.

+0

Tak, brzmi interesująco. – Cyan

2

Co powiecie na temat używania lseek() (lub _lseek()) z SEEK_END? Zwraca oczekiwane przesunięcie.

Pod Linuksem _FILE_OFFSET_BITS należy zdefiniować na 64 dla lseek(), aby zwrócić wartości 64-bitowe (które powinny być domyślne).

+0

Jeszcze tego nie próbowałem. Wydaje się, że lseek() może mieć taki sam problem jak fseeko(): używany typ (off_t) może lub nie może obsługiwać wartości powyżej 2 GB, w zależności od konfiguracji zewnętrznej. – Cyan

+0

@Attract: Testowałem to pod Linuksem 32/64-bitowym używając 'gcc' i pod 32-bitową wersją win-vista używając' VC10'. – alk

2

mam wdrożony i przetestowany, co następuje:

#if __WIN32__ 
#define stat64 _stat64 
#endif 

użyciu MinGW64 gcc 4.8.1 i Linux gcc 4.6.3 kompiluje i działa.

W systemie OSX nie jest wymagana ponowna definicja statystyk.

dla funkcji lstat i fstat Oczekuję podobnych makro #defines do działania.

+0

Czy to działa w wersjach 32-bitowych (Linux, Windows itp.)? – Cyan

Powiązane problemy