How can I figure out the size of a file, in bytes?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
-
You're going to need to use a library function to retrieve the details of a file. As C is completely platform independent, you're going to need to let us know what platform / operating system you're developing for!
From Chris Roberts -
as long as you have "iostream" available, you can do the following:
unsigned int fsize(char* file){ long begin,end; ifstream myfile (file); begin = myfile.tellg(); myfile.seekg (0, ios::end); end = myfile.tellg(); return end-begin; }
is the idea. My C++ chops are a little creaky, so pushing a char* to an ifstream might not work as I wrote it... a good look at tellg() and seekg() will help you get the details.
From Matt Dunnam -
If you're fine with using the std c library:
#include <sys/stat.h> off_t fsize(char *file) { struct stat; if (stat(file, &stat) == 0) { return stat.st_size; } return 0; }
From NilObject -
You can open the file, go to 0 offset relative from the bottom of the file with
#define SEEKBOTTOM 2 fseek(handle, 0, SEEKBOTTOM)
the value returned from fseek is the size of the file.
I didn't code in C for a long time, but I think it should work.
sigjuice : You shouldn't have to define something like SEEKBOTTOM. #includefseek(handle, 0, SEEK_END); From PabloG -
Matt's solution should work, except that it's C++ instead of C, and the initial tell shouldn't be necessary.
unsigned int fsize(char* file { FILE * f = fopen(file, "r"); fseek(f, 0, SEEK_END); return (unsigned int)ftell(f); }
Fixed your brace for you, too. ;)
From Derek Park -
Don't do this (why?):
Change the definition to int so that error messages can be transmitted, and then use fseek() and ftell() to determine the file size.
int fsize(char* file) { int size; FILE* fh; fh = fopen(file, "rb"); //binary mode if(fh != NULL){ if( fseek(fh, 0, SEEK_END) ){ fclose(fh); return -1; } size = ftell(fh); fclose(fh); return size; } return -1; //error }
mezhaka : Here is the report that unequivocally states that you should not do that: FIO19-C. Do not use fseek() and ftell() to compute the size of a file. It would be nice if you add this link to your answer, so the other people could see that clearly.superjoe30 : thanks. how's that?R.. : @mezhaka: That CERT report is simply wrong. `fseeko` and `ftello` (or `fseek` and `ftell` if you're stuck without the former and happy with limits on the file sizes you can work with) are the correct way to determine the length of a file. `stat`-based solutions **do not work** on many "files" (such as block devices) and are not portable to non-POSIX-ish systems.From superjoe30 -
A quick search in Google found a method using fseek and ftell and a thread with this question with answers that it can't be done in just C in another way.
You could use a portability library like NSPR (the library that powers Firefox) or check its implementation (rather hairy).
From Nickolay -
@NilObject That's not standard C. It's part of the POSIX standard, but not the C standard.
From Derek Park -
Don't use
int
. Files over 2 gigabytes in size are common as dirt these daysDon't use
unsigned int
. Files over 4 gigabytes in size are common as some slightly-less-common dirtIIRC the standard library defines
off_t
as an unsigned 64 bit integer, which is what everyone should be using. We can redefine that to be 128 bits in a few years when we start having 16 exabyte files hanging around.If you're on windows, you should use GetFileSizeEx - it actually uses a signed 64 bit integer, so they'll start hitting problems with 8 exabyte files. Foolish Microsoft! :-)
From Orion Edwards -
And if you're building a Windows app, use the GetFileSizeEx API as CRT file I/O is messy, especially for determining file length, due to peculiarities in file representations on different systems ;)
From James D -
Based on NilObject's code:
#include <sys/stat.h> off_t fsize(const char *filename) { struct stat st; if (stat(filename, &st) == 0) return st.st_size; return -1; }
Changes:
- Made the filename argument a
const char
. - Corrected the
struct stat
definition, which was missing the variable name. - Returns
-1
on error instead of0
, which would be ambiguous for an empty file.off_t
is a signed type so this is possible.
If you want
fsize()
to print a message on error, you can use this:#include <sys/stat.h> #include <string.h> #include <stdio.h> #include <errno.h> off_t fsize(const char *filename) { struct stat st; if (stat(filename, &st) == 0) return st.st_size; fprintf(stderr, "Cannot determine size of %s: %s\n", filename, strerror(errno)); return -1; }
On 32-bit systems you should compile this with the option
-D_FILE_OFFSET_BITS=64
, otherwiseoff_t
will only hold values up to 2 GB. See the "Using LFS" section of Large File Support in Linux for details.Drew Hall : This is Linux/Unix specific--probably worth pointing that out since the question didn't specify an OS.Ted Percival : You could probably change the return type to ssize_t and cast the size from an off_t without any trouble. It would seem to make more sense to use a ssize_t :-) (Not to be confused with size_t which is unsigned and cannot be used to indicate error.)From Ted Percival - Made the filename argument a
0 comments:
Post a Comment