2012-01-26 40 views
9

Trước khi mọi người phàn nàn về "trùng lặp", tôi đã kiểm tra SO khá kỹ lưỡng, nhưng dường như không có câu trả lời rõ ràng nào, mặc dù câu hỏi có vẻ khá đơn giản.Nhận kích thước tệp lớn trong C

Tôi đang tìm mã số di động C mã, có thể cung cấp kích thước tệp, ngay cả khi tệp lớn hơn 4GB.

Phương pháp thông thường (fseek, ftell) hoạt động tốt, miễn là tệp vẫn giữ nguyên là < 2GB. Nó được hỗ trợ khá tốt ở khắp mọi nơi, vì vậy tôi đang cố gắng tìm một thứ tương đương.

Thật không may, các phương thức được cập nhật (fseeko, ftello) không được tất cả các trình biên dịch hỗ trợ. Ví dụ, MinGW bỏ lỡ nó (và rõ ràng là MSVC). Hơn nữa, một số ý kiến ​​làm cho tôi tin rằng kiểu trả về mới (off_t) không nhất thiết phải hỗ trợ kích thước> 2GB, nó có thể phụ thuộc vào một số tham số bên ngoài, để được kiểm tra.

Các phương pháp rõ ràng (fseeko64, ftello64) không được MSVC hỗ trợ. MS cung cấp tương đương, _fseeki64 & _ftelli64. Điều này đã xấu, nhưng nó trở nên tồi tệ hơn: một số cấu hình Linux dường như hỗ trợ các chức năng này trong thời gian chạy. Ví dụ, Debian Squeeze của tôi trên PowerPC, sử dụng GCC 4.4, sẽ tạo ra một phương thức "filesize" bằng cách sử dụng fseeko64 luôn trả về 0 (trong khi nó hoạt động tốt cho Ubuntu64). MinGW dường như trả lời một số rác ngẫu nhiên trên 2GB.

Vâng, tôi hơi thất vọng về khả năng di động. Và nếu tôi cần thực hiện một loạt #if #else, thì tại sao không đi thẳng đến hệ điều hành của phương thức & trình biên dịch cụ thể ở vị trí đầu tiên, chẳng hạn như GetFileSize() cho MSVC chẳng hạn.

+3

Vâng, định nghĩa của bạn về "di động" là gì? Có nhiều hệ thống thậm chí không thể mở tệp. Thậm chí nhiều hơn, không thể mở các tệp có dung lượng trên 4 GB. –

Trả lời

8

Bạn đã nói: không có phương pháp di động; nếu tôi là bạn tôi chỉ cần đi với GetFileSize trên Windows và stat trên POSIX.

+2

Bạn có thể sử dụng '_stat64' trên Windows để giữ mã * sorta * giống nhau. – user7116

+1

@sixlettervariables: chính xác, mặc dù tôi không biết nếu mọi trình biên dịch trên Windows thực hiện nó (trong khi 'GetFileSize' là một phần của API Windows, do đó, nó luôn luôn nên có sẵn). –

+0

Thú vị. Tôi sẽ thử xem. – 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, đó là cách duy nhất theo tiêu chuẩn, nhưng tôi hy vọng bạn đang châm biếm: đọc toàn bộ tệp, có thể lớn hơn 2 GB, một ký tự đúng lúc chỉ biết kích thước của nó (trên hệ thống tệp hiện tại chỉ đơn giản là thuộc tính của tệp) là đồng bằng ngu ngốc ... –

+0

Tôi hy vọng đây là một trò đùa. – kichik

+2

Ồ, không, không, không ... hãy cho tôi biết bạn đang đùa. Mặt khác, câu hỏi là về một cách di động, không phải là một cách hiệu quả. Đây là một cách cầm tay thực sự. –

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

Có thể bạn có thể thử đọc câu hỏi. –

6

Bạn sẽ có thể sử dụng stat64 on Linux_stat64 on Windows để có được các thông tin về kích thước cho các tập tin trên 2 GB, và cả hai chức năng rất giống nhau trong cách sử dụng. Bạn cũng có thể sử dụng một vài #define s sử dụng stat64 trên Windows quá:

#if __WIN32__ 
#define stat64 _stat64 
#endif 

Tuy nhiên, mặc dù điều này nên làm việc, cần lưu ý rằng các gia đình _stat các chức năng trên Windows thực sự chỉ là một wrapper xung quanh các chức năng khác và sẽ bổ sung các tài nguyên bổ sung và phí thời gian.

+0

Có, âm thanh thú vị. – Cyan

2

Điều gì về việc sử dụng lseek() (hoặc _lseek()) với SEEK_END? Nó trả về số tiền đã tìm kiếm.

Dưới linux _FILE_OFFSET_BITS cần phải được định nghĩa để 64 cho lseek() để trở về giá trị 64bit (mà nên là mặc định dù sao đi nữa).

+0

Tôi chưa thử. Có vẻ như lseek() có thể có cùng một loại vấn đề như fseeko(): kiểu được sử dụng (off_t) có thể hoặc có thể không hỗ trợ các giá trị trên 2GB, tùy thuộc vào một số cấu hình bên ngoài. – Cyan

+0

@Attract: Tôi đã thử nghiệm điều này dưới 32/64bit linux bằng cách sử dụng 'gcc' và dưới 32bit win-vista sử dụng' VC10'. – alk

2

tôi đã thực hiện và thử nghiệm như sau:

#if __WIN32__ 
#define stat64 _stat64 
#endif 

sử dụng MinGW64 gcc biên dịch 4.8.1 và Linux gcc 4.6.3 biên dịch và các công trình.

Trên OSX, không cần xác định lại số liệu thống kê.

cho các hàm lstat và fstat tôi mong đợi macro tương tự #defines hoạt động.

+0

Điều đó có hoạt động trên các phiên bản 32 bit (Linux, Windows, v.v.) không? – Cyan

Các vấn đề liên quan