Làm thế nào tôi có thể tìm ra kích thước của một tập tin, tính bằng byte?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, tại sao không FILE* file
? -1
Làm thế nào tôi có thể tìm ra kích thước của một tập tin, tính bằng byte?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
char* file
, tại sao không FILE* file
? -1
Câu trả lời:
Dựa trên mã của 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;
}
Thay đổi:
const char
.struct stat
định nghĩa, thiếu tên biến.-1
về lỗi thay vì 0
, điều này sẽ mơ hồ cho một tệp trống. off_t
là một loại đã ký nên điều này là có thể.Nếu bạn muốn fsize()
in một thông báo bị lỗi, bạn có thể sử dụng điều này:
#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;
}
Trên các hệ thống 32 bit, bạn nên biên dịch tùy chọn này với tùy chọn -D_FILE_OFFSET_BITS=64
, nếu không off_t
sẽ chỉ giữ các giá trị tối đa 2 GB. Xem phần "Sử dụng LFS" của Hỗ trợ tệp lớn trong Linux để biết chi tiết.
fseek
+ ftell
theo đề xuất của Derek.
fseek
+ ftell
theo đề xuất của Derek. Số tiêu chuẩn C đặc biệt khẳng định rằng fseek()
để SEEK_END
trên một tập tin nhị phân là hành vi không xác định. 7.19.9.2 fseek
Hàm ... Luồng nhị phân không cần hỗ trợ một cách có ý nghĩa fseek
các cuộc gọi với giá trị từSEEK_END
, và như được lưu ý dưới đây, từ chú thích số 234 trên p. 267 của C chuẩn liên kết, và đó nhãn đặc biệt fseek
để SEEK_END
trong một dòng nhị phân như hành vi không xác định. .
Đừng sử dụng int
. Những tập tin có kích thước trên 2 gigabyte ngày nay rất phổ biến.
Đừng sử dụng unsigned int
. Các tệp có kích thước trên 4 gigabyte là phổ biến vì một số bụi bẩn ít phổ biến hơn
IIRC thư viện chuẩn định nghĩa off_t
là số nguyên 64 bit không dấu, đây là thứ mà mọi người nên sử dụng. Chúng ta có thể định nghĩa lại là 128 bit trong một vài năm khi chúng ta bắt đầu có 16 tệp exabyte treo xung quanh.
Nếu bạn đang ở trên windows, bạn nên sử dụng GetFileSizeEx - nó thực sự sử dụng số nguyên 64 bit đã ký, vì vậy họ sẽ bắt đầu gặp sự cố với 8 tệp exabyte. Microsoft ngu ngốc! :-)
Giải pháp của Matt sẽ hoạt động, ngoại trừ đó là C ++ thay vì C và thông báo ban đầu không cần thiết.
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;
}
Sửa lỗi niềng răng cho bạn, quá. ;)
Cập nhật: Đây thực sự không phải là giải pháp tốt nhất. Nó bị giới hạn ở các tệp 4GB trên Windows và nó có thể chậm hơn so với việc chỉ sử dụng một cuộc gọi dành riêng cho nền tảng như GetFileSizeEx
hoặc stat64
.
long int
từ ftell()
. (unsigned long)
đúc không cải thiện phạm vi như đã bị giới hạn bởi chức năng. ftell()
trả về -1 khi có lỗi và bị xáo trộn với diễn viên. Đề nghị fsize()
trả lại cùng loại với ftell()
.
** Đừng làm điều này ( tại sao? ):
Trích dẫn tài liệu chuẩn C99 mà tôi tìm thấy trực tuyến: "Đặt chỉ báo vị trí tệp thành cuối tệp, như với
fseek(file, 0, SEEK_END)
, có hành vi không xác định cho luồng nhị phân (vì có thể theo dõi các ký tự null) hoặc cho bất kỳ luồng nào có mã hóa phụ thuộc trạng thái điều đó không chắc chắn kết thúc ở trạng thái dịch chuyển ban đầu. **
Thay đổi định nghĩa thành int để thông báo lỗi có thể được truyền đi, sau đó sử dụng fseek()
và ftell()
để xác định kích thước tệp.
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
và ftello
(hoặc fseek
và ftell
nếu bạn bị mắc kẹt mà không có trước đây và hài lòng với các giới hạn về kích thước tệp bạn có thể làm việc) là cách chính xác để xác định độ dài của tệp. stat
các giải pháp dựa trên không hoạt động trên nhiều "tệp" (chẳng hạn như các thiết bị khối) và không khả dụng cho các hệ thống không phải POSIX-ish.
Các POSIX tiêu chuẩn có phương pháp riêng của mình để có được kích thước tập tin.
Bao gồm cáisys/stat.h
tiêu đề để sử dụng chức năng.
stat(3)
.st_size
tài sản.Lưu ý : Nó giới hạn kích thước 4GB
. Nếu không phải Fat32
hệ thống tập tin thì hãy sử dụng phiên bản 64 bit!
#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);
}
Các ANSI C không trực tiếp cung cấp cách thức để xác định độ dài của tập tin.
Chúng ta sẽ phải sử dụng tâm trí của chúng tôi. Hiện tại, chúng tôi sẽ sử dụng phương pháp tìm kiếm!
fseek(3)
.ftell(3)
.#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);
}
Nếu tập tin là
stdin
hoặc một đường ống. POSIX, ANSI C sẽ không hoạt động.
Nó sẽ trở lại0
nếu tập tin là một đường ống hoặcstdin
.Ý kiến : Bạn nên sử dụng tiêu chuẩn POSIX thay thế. Bởi vì, nó có hỗ trợ 64 bit.
struct _stat64
và __stat64()
cho _Windows.
Và nếu bạn đang xây dựng một ứng dụng Windows, hãy sử dụng API GetFileSizeEx vì I / O của tệp CRT rất lộn xộn, đặc biệt là để xác định độ dài tệp, do đặc thù trong cách biểu thị tệp trên các hệ thống khác nhau;)
Nếu bạn ổn với việc sử dụng thư viện 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;
}
Một tìm kiếm nhanh trong Google đã tìm thấy một phương pháp sử dụng fseek và ftell và một chủ đề với câu hỏi này với câu trả lời rằng nó không thể được thực hiện chỉ bằng C theo một cách khác.
Bạn có thể sử dụng thư viện tính di động như NSPR (thư viện hỗ trợ Firefox) hoặc kiểm tra việc triển khai của nó (khá nhiều lông).
Tôi đã sử dụng bộ mã này để tìm độ dài tập tin.
//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);
Thử cái này --
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
Điều này làm là đầu tiên, tìm đến cuối tập tin; sau đó, báo cáo nơi con trỏ tập tin. Cuối cùng (đây là tùy chọn) nó tua lại từ đầu tập tin. Lưu ý rằngfp
nên là một luồng nhị phân.
file_size chứa số byte mà tệp chứa. Lưu ý rằng vì (theo climits.h) loại dài không dấu được giới hạn ở 4294967295 byte (4 gigabyte), bạn sẽ cần tìm một loại biến khác nếu bạn có khả năng xử lý các tệp lớn hơn đó.
ftell
không trả về đại diện giá trị của số byte có thể được đọc từ tệp.
Đây là một chức năng đơn giản và sạch sẽ trả về kích thước tệp.
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
}
Bạn có thể mở tệp, chuyển đến 0 offset tương đối từ dưới cùng của tệp với
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
giá trị được trả về từ fseek là kích thước của tệp.
Tôi đã không viết mã trong C trong một thời gian dài, nhưng tôi nghĩ nó sẽ hoạt động.
Nhìn vào câu hỏi, ftell
có thể dễ dàng nhận được số byte.
long size = ftell(FILENAME);
printf("total size is %ld bytes",size);
ftell
đối số mô tả tệp, không phải là tên tệp, làm đối số.
ftell
không mong đợi một mô tả tập tin, nó mong đợi một FILE*
thay thế. Xem trang người đàn ông đầu tiên!
fseek()
đầu tiên để tìm kiếm phần cuối của tệp, và cũng ftell()
mong đợi FILE *
, không phải là một chuỗi! Bạn sẽ được phục vụ tốt để đưa ra câu trả lời của bạn.