Proper way to get file size in C

元气小坏坏 提交于 2020-01-24 12:05:31

问题


I am working on an assignment in socket programming in which I have to send a file between sparc and linux machine. Before sending the file in char stream I have to get the file size and tell the client. Here are some of the ways I tried to get the size but I am not sure which one is the proper one.

For testing purpose, I created a file with content " test" (space + (string)test)

Method 1 - Using fseeko() and ftello()

This is a method I found on https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file While the fssek() has a problem of "Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream", fseeko() is said to have tackled this problem but it only works on POSIX system (which is fine because the environment I am using is sparc and linux)

fd = open(file_path, O_RDONLY);
fp = fopen(file_path, "rb");
/* Ensure that the file is a regular file */
if ((fstat(fd, &st) != 0) || (!S_ISREG(st.st_mode))) {
  /* Handle error */
}
if (fseeko(fp, 0 , SEEK_END) != 0) {
  /* Handle error */
}
file_size = ftello(fp);
fseeko(fp, 0, SEEK_SET);
printf("file size %zu\n", file_size);

This method works fine and get the size correctly. However, it is limited to regular files only. I tried to google the term "regular file" but I still not quite understand it thoroughly. And I do not know if this function is reliable for my project.

Method 2 - Using strlen()

Since the max. size of a file in my project is 4MB, so I can just calloc a 4MB buffer. After that, the file is read into the buffer, and I tried to use the strlen to get the file size (or more correctly the length of content). Since strlen() is portable, can I use this method instead? The code snippet is like this

fp = fopen(file_path, "rb");
fread(file_buffer, 1024*1024*4, 1, fp);
printf("strlen %zu\n", strlen(file_buffer));

This method works too and returns

strlen 8

However, I couldn't see any similar approach on the Internet using this method. So I am thinking maybe I have missed something or there are some limitations of this approach which I haven't realized.


回答1:


Regular file means that it is nothing special like device, socket, pipe etc. but "normal" file. It seems that by your task description before sending you must retrieve size of normal file. So your way is right:

FILE* fp = fopen(...);
if(fp) {
  fseek(fp, 0 , SEEK_END);
  long fileSize = ftell(fp);
  fseek(fp, 0 , SEEK_SET);// needed for next read from beginning of file
  ...
  fclose(fp);
}

but you can do it without opening file:

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

struct stat buffer;
int         status;

status = stat("path to file", &buffer);
if(status == 0) {
  // size of file is in member buffer.st_size;
}



回答2:


OP can do it the easy way as "max. size of a file in my project is 4MB".

Rather than using strlen(), use the return value from fread(). stlen() stops on the first null character, so may report too small a value. @Sami Kuhmonen Also we do not know the data read contains any null character, so it may not be a string. Append a null character (and allocate +1) if code needs to use data as a string. But in that case, I'd expect the file needed to be open in text mode.

Note that many OS's do not even use allocated memory until it is written.
Why is malloc not "using up" the memory on my computer?

fp = fopen(file_path, "rb");
if (fp) {

  #define MAX_FILE_SIZE 4194304
  char *buf = malloc(MAX_FILE_SIZE);
  if (buf) {
    size_t numread = fread(buf, sizeof *buf, MAX_FILE_SIZE, fp);

    // shrink if desired
    char *tmp = realloc(buf, numread);
    if (tmp) {
      buf = tmp;

      // Use buf with numread char

    }
    free(buf);
  }
  fclose(fp);
}

Note: Reading the entire file into memory may not be the best idea to begin with.



来源:https://stackoverflow.com/questions/35390912/proper-way-to-get-file-size-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!