我如何能得到一个文件's大小在C?

我怎么能找到我用C写的应用程序打开的文件的大小? 我想知道大小,因为我想把加载文件的内容放入一个字符串,我使用malloc()分配。在我看来,只写malloc(10000*sizeof(char));是个坏主意。< / p >

1006977 次浏览

你需要搜索到文件的末尾,然后请求位置:

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

Linux / POSIX:

你可以使用stat(如果你知道文件名),或者fstat(如果你有文件描述符)。

下面是一个stat的例子:

#include <sys/stat.h>
struct stat st;
stat(filename, &st);
size = st.st_size;

Win32:

你可以使用GetFileSizeGetFileSizeEx

如果你在Linux上,认真考虑只使用glib中的< >强g_file_get_contents < / >强函数。它处理加载文件、分配内存和处理错误的所有代码。

如果你有文件描述符,fstat()返回一个包含文件大小的统计结构。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


// 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;
#include <stdio.h>


#define MAXNUMBER 1024


int main()
{
int i;
char a[MAXNUMBER];


FILE *fp = popen("du -b  /bin/bash", "r");


while((a[i++] = getc(fp))!= 9)
;


a[i] ='\0';


printf(" a is %s\n", a);


pclose(fp);
return 0;
}

HTH

您是否考虑过不计算文件大小,只在必要时增大数组?下面是一个例子(省略了错误检查):

#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)也可以工作。

如何使用< >强lseek < / >强/< >强fseek < / >强/< >强统计< / >强/< >强fstat < / >强获取文件大小?

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>


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 == -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 == -1)
{
printf("failed to lseek %s\n", filename);
exit(EXIT_FAILURE);
}


printf("[*] seek_filesize - file: %s, size: %lld\n", filename, (long long) 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 <file1> <file2>...\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;
}

我最后只做了一个简短而甜蜜的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)。