C++/size of file in C++
Expert: Ralph McArdell - 12/5/2004
Questionhi.
my question is: can we use the function "sizeof" to find out the size of a certain file? If yes how?because I tried to use sizeof(file-name) but I didnt get the actual size of the file.
Thank you.
Hanaa.
AnswerIn short no.
First sizeof is _not_ a function it is an operator. You use it to obtain the size of a type or an object. This is resolved by the compiler at compile time.
The operand (that is the argument) of the sizeof operator is either an expression or a parenthesised type name so you can say:
sizeof object
or
sizeof( type_name )
or - as the operand may be an expression:
sizeof( object )
or even something like:
sizeof( tan(x)/scale )
In each case the only thing that the compiler is interested in is either the size of the type of the result of the expression or the size of the type named in parentheses. In nearly all cases in C and C++ an expression provided to sizeof is _not_ evaluated - so in the last case tan(x) / scale is not evaluated. The exception, as far as I can tell, is for a of feature that is only part of the latest standard of C - C99 - called a variable length array, where the expression is evaluated.
The result of sizeof is an unsigned integer type called size_t - which is defined in <stddef.h> (for C) or <cstddef> (for C++), and possibly other header files as well. Its value is the size, in units of char (i.e. char has a size of 1), required for objects of the type represented by the result of the expression or the type name operand.
If fact the standards say that the result of sizeof is "the number of bytes in the object representation of its operand" and that "sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1". The quotes were taken from the latest edition of the C++ standard, section 5.3.3 Sizeof, but the C 1999 standard has similar text.
Common values for a compiler for a 32-bit target system are:
sizeof( short ) is 2
sizeof( int ) is 4
sizeof( long ) is 4
sizeof( float ) is 4
sizeof( double ) is 8
However, the size of built in types is implementation defined. Note that the size of compound types - struct, class, union - may not be the sum of the size of their data members for various reasons such as padding between data members to align them correctly in memory and housekeeping information such as vtable pointers (for C++ classes with virtual members).
A common use is to find the number of elements in an array (a C_style built-in array that is):
size_t numberOfElements( sizeof array / sizeof(elementType) );
Which is especially useful if the array was defined without a dimension but with initialisation data:
int mapping[] =
{ 1, 2, 3, 6, 6, 9, 0, 0, -1, -8, 4, 7, -9, 0, 5 };
size_t mappingSize( sizeof mapping / sizeof(int) );
Then if you go back and add or remove values to mapping the mappingSize will be updated accordingly.
Secondly, with regard to finding the size of a file, there is no easy standard way to do this. The most obvious way would be to seek to the end of a file then get the current file position.
Now you could do this using C++ IOStreams - using the likes of std::basic_istream::seekg, std::basic_istream::tellg and std::basic_ostream::seekp, std::basic_ostream::tellp. In such cases you would specify seeking relative to the end of the file using something like:
inFileStream.seekg( 0, std::ios::end );
You then call tellg on inFileStream to find its position (which is the last byte of the file, assuming you are using a byte based character type for your stream as is probably the case with std::ifstream):
std::ios::pos_type pos = inFileStream.tellg();
However there is a slight fly in the ointment - std::ios::pos_type is no longer just an integral value representing the current file position - it is a type that may contain other information such as conversion state of streams based on multi-byte characters.
So, in the light of this complexity, it would probably be better to use the standard C file I/O functions fseek and ftell (together with fopen and fclose and a C FILE type object):
FILE * stream = fopen( fileName, "r" );
fseek( stream, 0L, SEEK_END );
long endPos = ftell( stream );
fclose( stream );
Of course there are operating system specific ways to get the file size. UN*X like operating systems have the stat functions (stat, fstat and lstat) - which return information on a file in a stat struct. The stat member of interest here is the st_size member - which is the file size in bytes. See the man pages on any UN*X or UN*X like system for details or try an online search for
man stat
or similar.
Microsoft Win32 systems such as Windows NT, 2000, XP, Me, 98 and 95 have the GetFileSize and GetFileSizeEx functions and the MSVC++ runtime library has the _stat functions - which are like the UN*X stat functions in that they use a _stat struct with a st_size member - and the _filelength function. See the MSDN library for details on these and other Microsoft development topics (online at
http://www.msdn.microsoft.com/).
A C++ solution would be to use the Boost (
http://www.boost.org) file system library (
http://www.boost.org/libs/filesystem/doc/index.htm) - check out the operation.hpp documentation for the operations function file_size (
http://www.boost.org/libs/filesystem/doc/operations.htm).