Is it recommended method for computing the size of

2019-08-11 09:04发布

In C, we can find the size of file using fseek() function. Like,

if (fseek(fp, 0L, SEEK_END) != 0)
{
    //  Handle repositioning error
}

So, I have a question, Is it recommended method for computing the size of a file using fseek() and ftell()?

标签: c file
4条回答
时光不老,我们不散
2楼-- · 2019-08-11 09:30

If you're on Linux or some other UNIX like system, what you want is the stat function:

struct stat statbuf;
int rval;

rval = stat(path_to_file, &statbuf);
if (rval == -1) {
    perror("stat failed");
} else {
    printf("file size = %lld\n", (long long)statbuf.st_size;
}

On Windows under MSVC, you can use _stati64:

struct _stati64 statbuf;
int rval;

rval = _stati64(path_to_file, &statbuf);
if (rval == -1) {
    perror("_stati64 failed");
} else {
    printf("file size = %lld\n", (long long)statbuf.st_size;
}

Unlike using fseek, this method doesn't involve opening the file or seeking through it. It just reads the file metadata.

查看更多
放荡不羁爱自由
3楼-- · 2019-08-11 09:32

Well, you can estimate the size of a file in several ways:

  • You can read(2) the file from the beginning to the end, and the number or chars read is the size of the file. This is a tedious way of getting the size of a file, as you have to read the whole file to get the size. But if the operating system doesn't allow to position the file pointer arbitrarily, then this is the only way to get the file size.
  • Or you can move the pointer at the end of file position. This is the lseek(2) you showed in the question, but be careful that you have to do the system call twice, as the value returned is the actual position before moving the pointer to the desired place.
  • Or you can use the stat(2) system call, that will tell you all the administrative information of the file, like the owner, group, permissions, size, number of blocks the file occupies in the disk, disk this file belongs to, number of directory entries pointing to it, etc. This allows you to get all this information with only one syscall.

Other methods you point (like the use of the ftell(3) stdio library call) will work also (with the same problem that it results in two system calls to set and retrieve/restore the file pointer) but have the problem of involving libraries that probably you are not using for anything else. It should be complicated to get a FILE * pointer (e.g. fdopen(3)) on a int file descriptor, just to be able to use the ftell(3) function on it (twice), and then fclose(3) it again.

查看更多
别忘想泡老子
4楼-- · 2019-08-11 09:42

The fseek()/ftell() works sometimes.

if (fseek(fp, 0L, SEEK_END) != 0) 
  printf("Size: %ld\n", ftell(fp));
}

Problems.

  1. If the file size exceeds about LONG_MAX, long int ftell(FILE *stream) response is problematic.

  2. If the file is opened in text mode, the return value from ftell() may not correspond to the file length. "For a text stream, its file position indicator contains unspecified information," C11dr §7.21.9.4 2

  3. If the file is opened in binary mode, fseek(fp, 0L, SEEK_END) is not well defined. "Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state." C11dr footnote 268. @Evert This most often applies to earlier platforms than today, but it is still part of the spec.

  4. If the file is a stream like a serial input or stdin, fseek(file, 0, SEEK_END) makes little sense.

The usual solution to finding file size is a non-portable platform specific one. Example good answer @dbush.

Note: If code attempts to allocate memory based on file size, the memory available can easily be exceeded by the file size.

Due to these issues, I do not recommend this approach.

Typically the problem should be re-worked to not need to find the file size, but to grow the data as more input is processed.


LL disclaimer: Note that C spec footnotes are informative and so not necessarily normative.

查看更多
霸刀☆藐视天下
5楼-- · 2019-08-11 09:46

The best method in my opinion is fstat(): https://linux.die.net/man/2/fstat

查看更多
登录 后发表回答