tags:

views:

39109

answers:

10

How can I find out the size of a file? I opened with an application written in C. I would like to know the size, because I want to put the content of the loaded file into a string, which I alloc using malloc(). Just writing malloc(10000*sizeof(char)); is IMHO a bad idea.

+20  A: 

You need to seek to the end of the file and then ask for the position:

fseek(fp, 0L, SEEK_END);
sz = ftell(fp);

You can then seek back to the beginning:

fseek(fp, 0L, SEEK_SET);
Rob Walker
If you use ftell, then you must open the file in binary mode. If you open it in text mode, ftell only returns a "cookie" that is only usable by fseek.
camh
@camh - Thanks man. This comment solved a problem I had with a file sizing algorithm. For the record, one opens a file in binary mode by putting a 'b' at the end of fopen's mode string.
T.E.D.
+50  A: 

There are two basic methods:

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

Or, you can use stat, if you know the filename:

struct stat st;
stat(filename, &st);
size = st.st_size;
Greg Hewgill
needs error checking
ysth
Please note that I have omitted error checking in the interest of clarity.
Greg Hewgill
You don't need the filename - you can use fstat for that.
Tanktalus
You need to point stat the address of the struct. The second line should be:stat(filename,
Goose Bumper
@aditya: Thanks for that, fixed.
Greg Hewgill
+6  A: 

If you're on Linux, seriously consider just using the g_file_get_contents function from glib. It handles all the code for loading a file, allocating memory, and handling errors.

Ben Combee
If you're on Linux *and* want to have a dependency on glib, that is.
JesperE
Not that bad of a problem, as glib is used by both GTK and KDE applications now. It's also available on Mac OS X and Windows, but it's not nearly as standard there.
Ben Combee
+15  A: 

If you have the file descriptor fstat() returns a stat structure which contain the file size.

   #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);
    int size = buf.st_size;
PiedPiper
Add "fd = fileno(f);" if you have a stream (e.g. from fopen), not a file descriptor. Needs error checking.
ysth
Of course it needs error checking - that would just complicate the example.
PiedPiper
+3  A: 

I've always used this method:

FILE *fd = fopen(...);
long size = filelength(fileno(fd));

if you're using file descriptors or

int f = open(...);
long size = filelength(f);

For low-level IO.

It seems like the simplest way to get a file's size. There's no need to do a couple of seeks.

For what you're doing though, you might want to consider using mmap and just map the file into your memory space.

Ferruccio
is there an #include for 'filelength' ?("man filelength" turned up nothing)
JustJeff
@JustJeff - I always thought that filelength() was a Posix function found in sys/io.h, but I searched the include directories on both an OSX and a Linux box without finding any prototypes for it. It might be that it's only supported by the Microsoft tools, but MSDN documents it as a Posix function. Strange.
Ferruccio
A: 
#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

plan9assembler
+2  A: 

Have you considered not computing the file size and just growing the array if necessary? Here's an example (with error checking ommitted):

#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;
}

This has the advantage of working even for streams in which it is impossible to get the file size (like stdin).

Pat Morin
A: 
#include <stdio.h>

int main(void)
{

   FILE *fp;
   char filename[80];
   long length;

   printf("input file name:");
   gets(filename);
   fp=fopen(filename,"rb");

   if(fp==NULL) {
      printf("file not found!\n");
   }
   else {
      fseek(fp,OL,SEEK_END);
      length=ftell(fp);
      printf("the file's length is %1dB\n",length);
      fclose(fp);
   }

   return 0;
}
lezard
A: 

To the OP: don't forget that sizeof(char) always evaluates to 1. Always.

pete
A: 

if i want how many characters like "ABC" are in the file and if I use the lseek(fp,oL,2) as many of you told if the file has many lines the result will not be the number of the characters ,,, for example: "file.txt"
ABC (new line) HGF

the method with the lseek will give 8 as result but the characters are 6.

Jim