File size from iostream?

SirHC
SirHC used Ask the Experts™
on
In a function that takes an ofstream (or ofstream&) as an argument, is there a way to determine the size in bytes of the file that the ofstream is attached to?  E.g. the stream equivalent of fstat() ...

(Failing a direct equivalent, is there any way to get the filename/ filepath that the stream is attached to?  I could use stat() on that, if I could get it.)

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
You can use seekp
Commented:
You can use seekp to position the streampos at the end, and use tellp to get the end position.
That will give you the length.
Example:
int main(int argc, char* argv[])
{
     ofstream foo;
     foo.open("test.txt");
     foo << "Hello World!" << endl;
     foo.seekp(0, ios::end);
     cout << "This file length is " << foo.tellp() << endl;
     return 0;
}

Author

Commented:
Are you *sure* about that?

I have two objections; these -may- turn out to be platform-dependent or even obsolete, but that may be the source of my confusion.

1) Here on Solaris 2.8, seekp()/tellp are documented only for OUTPUT streams; your example also operates on an OUTPUT stream.  I am interested in INPUT streams.  

  1a) Granted, the OSTREAM(3CC4) manpage here is confusing.  In discussing tellp()/seekp(), it first states that "these [functions] deal with the put pointer of the streambuf associated with an ostream," then later in the same paragraph says that "seeks done on the istream rather than the streambuf..." will affect the [position], bla bla bla...  So is there an istream associated with each ostream, or has there been a lapse in editing of the manpage text?  I dunno...

2) It's been a while since I last looked up these docs, and in the past I recall the descriptions of seekp() / tellp() stating that the argument/return value is of type 'streampos,' and cautioning the programmer NOT to assume this is an integer value-in-bytes, and therefore NOT to perform arithmetic operations on the value.  Ergo, your treatment of the 'streampos' as "the file size," strictly speaking, violates this usage stricture.  On the other hand, my manpages seem to have been updated since then, and I cannot find the caveat anymore.  Maybe Sun decided to fall back from their earlier cautionary position.  Anybody know?

Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Commented:
>>I am interested in INPUT streams.  

Your question ask about using ofstream, which is an output stream.

You can still do this with an input stream, but you need to use tellg and seekg instead.

Commented:
>>2) It's been a while since I last looked up these docs,
>>and in the past
For generic portable codeing, that is still correct.
However, I'm not aware of any platform that doesn't have streampos as an integer or a long.
In any case, if you want your code to be safe and very poratble, then use streampos type to determine the size of your file, and don't use an integer.

Commented:
>>1a) Granted, the OSTREAM(3CC4) manpage here is confusing.

I don't understand 1a).
Can you rephrase it, or be more specific?
// to make this work with iostream should be easy

#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

main(void)
{
char filename[50];
struct _stat buf;
int result;
long int fsize;

printf("Enter filename :");
scanf("%s",&filename);

result = _stat(filename,&buf );

fsize = buf.st_size;

printf("\n Filesize in bytes is %li",fsize);

return 0;
}

Commented:
ummm.... How is that working WITH iostream???
lol it aint, but its simpley done with sys/stat.h and that structure

Author

Commented:
1) Whoops, by golly, you're right -- I misspoke in my original question.  First day here, lots of confusion. :-)  I -meant- to say, "ifstream," originally.  Sheesh. :-b

2) Technically, the intent of Sun's using a custom datatype such as 'streampos' rather than an arithmetic type such as 'int' or 'long,' directly, is specifically to PREVENT programmers from assuming, and coming to depend on, the value's being usable as an arithmetic type.  I don't want to break that rule just because "that's the only way to make it work."

3) Re: the confusing language in the manpage.  Okay, there are at least three different manpages here for the topic of 'ostream': OSTREAM(3C++), basic_ostream(3C++), and OSTREAM(3CC4).  I have no idea how these relate to each other: which, if any, of these is "the" ostream manpage, or whether the presence of multiple OSTREAM docs indicates multiple competing implementations of output streams, "or what."  I don't really even know which implementation (if there are multiples) my environment uses.  I just say "#include <fstream.h>" and cross my fingers, ya know?  Anyway, the third of those manpages contains text which, with apologies to Sun, I hereby quote verbatim:
  "Positioning functions
     These deal with the put pointer of the streambuf associated
     with an ostream.  See sbufpub(3CC4) for a complete discus-
     sion.  Multibyte input operations may cause the get pointer
     of the streambuf to differ from the value reported by
     tellg(), but seeks done on the istream rather than the
     streambuf will still coordinate correctly with all opera-
     tions on the istream."

As to the confusion, it is simply, "WHAT istream?"  This is an OSTREAM manpage.  Is 'istream' discussed here by mistake, or is there really, truly, an istream involved somewhere in the implementation of the ostream?  I don't know how much more explicit I can be about why this text is nonsensical.  It "should" be talking about an ostream, yet it talks about an istream.  I'm confused by that.

Author

Commented:
(Another remark on that "confusing" text in the OSTREAM(3CC4) manpage.  That paragraph I quoted speaks of "input operations," as well.  Which also doesn't make a lot of sense in a manpage about OUTPUT streams.)

Commented:
I'm still not sure what your question is for 3), but in any case, you can use seekp/tellp for Out-Stream and use seekg/tellg for In-Stream.

So using the code I proviously posted, you can put the appropriate function call for the associated stream type, and that well get you the length.
In all implementations that I've worked on, you can assigned the return value of tellg/tellp to an unsigned long variable with NO casting.
Example code:

int main(int argc, char* argv[])
{
     ifstream foo;
     foo.open("test.txt");
     foo.seekg(0, ios::end);
     unsigned long LengthOfFile = foo.tellg();
     cout << "This file length is " << LengthOfFile << endl;
     return 0;
}

Using the tellX() function is the standard way of finding the length of the file via ANSI C++ only code.

Commented:
FYI:
I've worked with Solaris, and above code will definitely work with no problem on Solaris or any other common UNIX platform.

Author

Commented:
Ah.  tellg()/seekg() !  Never thought of that -- a suffix of 'p' (as in 'put') for output, and a suffix of 'g' (as in 'get') for input.  That makes sense, in retrospect.  Our manpages here are extraordinarily impenetrable, to the extent that I never found tellg()/seekg() and wouldn't even have thought to LOOK for them.  THANK YOU for pointing this out.  

My problem with 3) is simply that when an 'ostream' manpage starts talking about 'istreams,' "something seems wrong."  Either I am failing to understand a legitimate reason for discussing istreams in an ostream manpage, or this text "as is" is in error -- either it's in the wrong manpage entirely, or it says "istream" where it should say "ostream," etc.  Now that I hear about seekg()/tellg() which parallel, for input streams, seekp()/tellp() for output streams, my suspicion is an editing error in the preparation of the manpage.  I suspect someone at Sun cut-and-pasted the description of seekg()/tellg() from the 'istream' manpage, into the 'ostream' manpage, edited the function names to change the 'g' suffix to 'p', but forgot to edit the explanatory text to refer to 'output operations' and 'ostreams' rather than 'input operations' and 'istreams'.  Am I the only one who sees this?  How can anyone read the text I quoted previously, and NOT find it confusing in the context of an ostream manpage?

I am going to have to accept your argument that "'streampos' can be assigned to a long without casting."  Looking at the OSTREAM(3CC4) and ISTREAM(3C++) manpages, I observe that they both document 'streampos' as a typedef for 'long'.  That, plus the apparent removal of the warning NOT to treat 'streampos' as an arithmetic type, could be taken to mean that we're no longer forbidden to do so, and your technique is acceptable.  (If not for the documentation change, however, I would have continued to argue that "I don't care if it works, you're NOT SUPPOSED TO DO THAT."  The philosophical intent is more important to me than simply "getting it to work."  What can I say, I'm "old school.")

Regardless, thank you (all) once again for your input.

(Now, how do I close this question and rate the answers I've received here?)

Commented:
>>(Now, how do I close this question and rate the answers I've received here?)

The gray area next to the comment, you'll see a "Accept Comment As Answer" link.  Click on that link, and it'll convert the comment to an accepted answer.

Good Luck

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial