您需要寻找文件的末尾然后询问位置:
fseek(fp, 0L, SEEK_END); sz = ftell(fp);
然后你可以回头,例如:
fseek(fp, 0L, SEEK_SET);
或者(如果想要开始)
rewind(fp);
返回有符号的int,因此限制为2 GB.但从好的方面来说,你的文件可能是20亿字节的负数,并且他们已为此做好准备. (98认同)
呃,在人们忘记它意味着什么之前,先使用[`rewind`](http://www.cplusplus.com/reference/clibrary/cstdio/rewind/) (59认同)
来自[fseek documentation](http://www.cplusplus.com/reference/cstdio/fseek/)"允许库实现无意义地支持SEEK_END(因此,使用它的代码没有真正的标准可移植性)." (21认同)
`length = lseek(fd,0,SEEK_END)+1;` (18认同)
@camh - 谢谢你.这个评论解决了我使用文件大小调整算法时遇到的问题.对于记录,通过在fopen的模式字符串的末尾加上'b',以二进制模式打开文件. (11认同)
这不是便携式的.不要使用这个.它不符合POSIX标准 (6认同)
大声笑,是的,Windows从DOS继承了这种愚蠢的文本/二进制模式废话.现在很容易忘记这一点.实际上POSIX标准甚至要求任何POSIX系统必须能够处理fopen调用中的"b"标志(与C标准兼容!),但同时它要求,实现必须完全忽略它,因为这个标志对POSIX系统没有影响(那些人不知道文本模式这样的东西,总是以二进制模式打开). (4认同)
使用fseeko和ftello可以避免> 2GB的概率.如果可能的话编辑答案.!! (2认同)
@RobWalker:https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+ + A +常规+文件 (2认同)
Greg Hewgill.. 360
假设您的实现有意义地支持SEEK_END:
fseek(f, 0, SEEK_END); // seek to end of file size = ftell(f); // get current file pointer fseek(f, 0, SEEK_SET); // seek back to beginning of file // proceed with allocating memory and reading the file
您可以使用stat
(如果您知道文件名),或fstat
(如果您有文件描述符).
以下是stat的示例:
#includestruct stat st; stat(filename, &st); size = st.st_size;
您可以使用GetFileSize或GetFileSizeEx.
您需要寻找文件的末尾然后询问位置:
fseek(fp, 0L, SEEK_END); sz = ftell(fp);
然后你可以回头,例如:
fseek(fp, 0L, SEEK_SET);
或者(如果想要开始)
rewind(fp);
假设您的实现有意义地支持SEEK_END:
fseek(f, 0, SEEK_END); // seek to end of file size = ftell(f); // get current file pointer fseek(f, 0, SEEK_SET); // seek back to beginning of file // proceed with allocating memory and reading the file
您可以使用stat
(如果您知道文件名),或fstat
(如果您有文件描述符).
以下是stat的示例:
#includestruct stat st; stat(filename, &st); size = st.st_size;
您可以使用GetFileSize或GetFileSizeEx.
如果您有文件描述符 fstat()
返回包含文件大小的stat结构.
#include#include #include // fd = fileno(f); //if you have a stream (e.g. from fopen), not a file descriptor. struct stat buf; fstat(fd, &buf); off_t size = buf.st_size;
我最后只是做了一个简短而有趣的fsize
功能(注意,没有错误检查)
int fsize(FILE *fp){ int prev=ftell(fp); fseek(fp, 0L, SEEK_END); int sz=ftell(fp); fseek(fp,prev,SEEK_SET); //go back to where we were return sz; }
标准C库没有这样的功能有点愚蠢,但我可以看出为什么它很难,因为不是每个"文件"都有一个大小(例如/dev/null
)
如何使用lseek / fseek / stat / fstat获取文件大小?
#include#include #include #include #include void fseek_filesize(const char *filename) { FILE *fp = NULL; long off; fp = fopen(filename, "r"); if (fp == NULL) { printf("failed to fopen %s\n", filename); exit(EXIT_FAILURE); } if (fseek(fp, 0, SEEK_END) == -1) { printf("failed to fseek %s\n", filename); exit(EXIT_FAILURE); } off = ftell(fp); if (off == (long)-1) { printf("failed to ftell %s\n", filename); exit(EXIT_FAILURE); } printf("[*] fseek_filesize - file: %s, size: %ld\n", filename, off); if (fclose(fp) != 0) { printf("failed to fclose %s\n", filename); exit(EXIT_FAILURE); } } void fstat_filesize(const char *filename) { int fd; struct stat statbuf; fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP); if (fd == -1) { printf("failed to open %s\n", filename); exit(EXIT_FAILURE); } if (fstat(fd, &statbuf) == -1) { printf("failed to fstat %s\n", filename); exit(EXIT_FAILURE); } printf("[*] fstat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size); if (close(fd) == -1) { printf("failed to fclose %s\n", filename); exit(EXIT_FAILURE); } } void stat_filesize(const char *filename) { struct stat statbuf; if (stat(filename, &statbuf) == -1) { printf("failed to stat %s\n", filename); exit(EXIT_FAILURE); } printf("[*] stat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size); } void seek_filesize(const char *filename) { int fd; off_t off; if (filename == NULL) { printf("invalid filename\n"); exit(EXIT_FAILURE); } fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP); if (fd == -1) { printf("failed to open %s\n", filename); exit(EXIT_FAILURE); } off = lseek(fd, 0, SEEK_END); if (off == (off_t)-1) { printf("failed to lseek %s\n", filename); exit(EXIT_FAILURE); } printf("[*] seek_filesize - file: %s, size: %lld\n", filename, off); if (close(fd) == -1) { printf("failed to close %s\n", filename); exit(EXIT_FAILURE); } } int main(int argc, const char *argv[]) { int i; if (argc < 2) { printf("%s ...\n", argv[0]); exit(0); } for(i = 1; i < argc; i++) { seek_filesize(argv[i]); stat_filesize(argv[i]); fstat_filesize(argv[i]); fseek_filesize(argv[i]); } return 0; }
您是否考虑过不计算文件大小而只是在必要时增加数组?这是一个例子(省略错误检查):
#define CHUNK 1024 /* Read the contents of a file into a buffer. Return the size of the file * and set buf to point to a buffer allocated with malloc that contains * the file contents. */ int read_file(FILE *fp, char **buf) { int n, np; char *b, *b2; n = CHUNK; np = n; b = malloc(sizeof(char)*n); while ((r = fread(b, sizeof(char), CHUNK, fp)) > 0) { n += r; if (np - n < CHUNK) { np *= 2; // buffer is too small, the next read could overflow! b2 = malloc(np*sizeof(char)); memcpy(b2, b, n * sizeof(char)); free(b); b = b2; } } *buf = b; return n; }
这样做的优点是即使对于无法获得文件大小的流(如stdin)也能工作.
如果您使用的是Linux,请认真考虑使用glib中的g_file_get_contents函数.它处理加载文件,分配内存和处理错误的所有代码.