• Advertisement

Archived

This topic is now archived and is closed to further replies.

Files I/O operations in C++.

This topic is 5149 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi every-1. I''m currently trying to figure out how the C++ fstream classes (both I and O) work. I''ve been taught everywhere the gcount() method returned the number of characters extracted during the last operation. But does it really return the count of characters actually read of asked?? If if write fin.read(buffer,100), but less than 100 char are actually present in the file, for example, should gcount() return 100 or ''less than 100''?? Then how can I count the chars in a file. I''ve been trying something like the following but the loop never ends :
int nCharCount = 1; //the null character at least

char *buffer = null;
while(!fin.eof()){
	fin.peek();
	nCharCount++;
   }
buffer = new char[nCharCount];
// this latter statement never gets reached, but WTH ???

Prog, Hex & Rock''n''Roll : I don''t like the Prog but the Prog likes me. Some nice poetry to sweeten your spirit and relax a bit before programming

Share this post


Link to post
Share on other sites
Advertisement
.peek() doesn''t advance the position in the stream, which is why your loop doesn''t exit. What happens is

1) fin.eof() is false
2) fin.peek() reads the first character and returns that value, which subsequently is discarded because it''s not assigned anywhere.
3) nCharCount is incremented
4) goto 1.

If the general problem you have is, as it seems, "I want to read a file completely into memory, but I don''t know ahead of time how much memory to allocate", then - FFS, use a Vector. It will make your life easier

Share this post


Link to post
Share on other sites
I would think you could do std::distance((std::istreambuf_iterator<char>(myIfstream)), std::istreambuf_iterator<char>());.

Share this post


Link to post
Share on other sites
Thank you all buddies. I''ll try to keep simple for now, so the basic fstream''s input functions should do. Templates will wait a bit more (at least until I''ve parsed the new GameDev''s templates article). I think seekg and tellg will do it. :-)

Prog, Hex & Rock''n''Roll :
I don''t like the Prog but the Prog likes me.
Some nice poetry to sweeten your spirit and relax a bit before programming

Share this post


Link to post
Share on other sites
seekg and tellg cannot do it portably, I believe, as there need be no conversion between a streamsize and an integral type.

The method I described -- which requires reading every byte of the file -- is the one you must use.


[edited by - DrPizza on January 13, 2004 10:18:34 AM]

Share this post


Link to post
Share on other sites
Not really, I''ve seen a third party standard library implementation where the streamsize was a class that wrapped 64 bit artihmetic on a compiler that didn''t have a primitive type for 64 bit integers.

Share this post


Link to post
Share on other sites
Well, unless he is trying to write an extremely portable app, which based on the fact that he is still learning basic file I/O operations, I doubt, then seekg/tellg along with seekp/tellp should be fine.

Btw, here's some "simple" code as you asked for:


unsigned long textSize;
fstream file("text.txt");

//do error checking on open operation

file.seekg(0, ios::end);
textSize = file.tellg() - file.tellp();


You could then read in the entire file by:


char* buffer = new char[textSize];
file.tellg(0, ios::beg);
file.read(buffer, textSize);


To do it in your loop you need to change peek() to get(), however, while the code I've listed may have a few more lines of code than your loop, I believe it is much more direct and explicit as to what is being done. If your goal is to read in the entire file into a single buffer, then there is no reason for a separate read operation for each byte. Using a loop to read in a file is entirely useful and justified when you wish to perform operations on, or with, each separate datum from the file, though.

peace and (trance) out

Mage

[Edit: Fixed broken formatting.]

[edited by - Oluseyi on January 14, 2004 12:41:09 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor
Isn''t that like saying float doesn''t *have* to be a floating-point type, it _could_ be a fixed-point type with lots of digits?


No.

Share this post


Link to post
Share on other sites
quote:
Well, unless he is trying to write an extremely portable app, which based on the fact that he is still learning basic file I/O operations, I doubt, then seekg/tellg along with seekp/tellp should be fine.

It''s not a question of "portable". It''s a question of "correct". The expression I posted is the canonical way of determining a file length in C++. What you have posted is not correct . It''s that simple.

Share this post


Link to post
Share on other sites
Hi again. Thanks to you all ; I think what I actually needed was fin.seekg(0,ios::end) and length = fin.tellg();.
I don''t currently really care about portability for now, since Linux satisfies me. ;-)

Prog, Hex & Rock''n''Roll :
I don''t like the Prog but the Prog likes me.
Some nice poetry to sweeten your spirit and relax a bit before programming

Share this post


Link to post
Share on other sites

#include <iostream>

#include <fstream>

#include <string>

size_t get_file_length(const std::string& filename)
{
std::ifstream file(filename.c_str());
std::string fcontents(
std::istream_iterator<char>(file),
std::istream_iterator<char>()
);
return fcontents.length();
}


EDIT: Note that this won't work accurately for binary files.


daerid | Legends | Garage Games | Spirit | Hapy | Boost | Python | Google
"Doomed to crumble, unless we grow, and strengthen our communication" - Maynard James Keenan, Tool


[edited by - daerid on January 14, 2004 1:25:56 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by KurtCPP
I don''t currently really care about portability for now, since Linux satisfies me. ;-)


If you''re going to work only on Linux, you might as well just use the stat() function (or one of its siblings).

Share this post


Link to post
Share on other sites
SiCrane :
Yes, I could use the stat() function but this wasn''t realy the point, since my purpose was actually to get used to using the fstream methods.

Daerid:
I didn''t even know a string class existed in C++. Actually, I knew the CString class but it belongs to MFC (yuck.).
And how comes you can specify the files'' names without the ''.h''?? Is this really related to templates??

Thank you for help. :-)

Prog, Hex & Rock''n''Roll :
I don''t like the Prog but the Prog likes me.
Some nice poetry to sweeten your spirit and relax a bit before programming

Share this post


Link to post
Share on other sites
quote:
Original post by KurtCPP
And how comes you can specify the files'' names without the ''.h''?? Is this really related to templates??


NONE of the standard C++ header files have a ''.h''.


“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”
— Brian W. Kernighan (C programming language co-inventor)

Share this post


Link to post
Share on other sites
quote:
Original post by KurtCPP
Hey, I had never been told this !!!!!!!! So what exactly are the .h'ed files, then ??? Non standard files?? Then why do they keep existins??


Either non-standard files (iostream.h, fstream.h, strstream.h don't use ANY of these ) or C files, standard (stdio.h, stdlib.h) or not (windows.h, conio.h ...)

Standard C++ headers that are inherited from C lose their .h and gain a 'c' prefix, so <stdio.h> -> <cstdio>, <stdlib.h> -> <cstdlib>, <string.h> -> <cstring>, <ctype.h> -> <cctype>.

Therefore: <string> C++ string class header, <cstring> C++ header for C strings, <string.h> C header for C strings.

Simple, no ?

And they keep existing for backward-compatibility.


“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”
— Brian W. Kernighan (C programming language co-inventor)


[edited by - Fruny on January 15, 2004 5:32:54 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by daerid

#include <iostream>

#include <fstream>

#include <string>

size_t get_file_length(const std::string& filename)
{
std::ifstream file(filename.c_str());
std::string fcontents(
std::istream_iterator<char>(file),
std::istream_iterator<char>()
);
return fcontents.length();
}


EDIT: Note that this won''t work accurately for binary files.



Dumping it into a string is a waste of time and memory; std::distance() will tell you how far apart the iterators are without recording what''s in the file.

And using istream_iterators is wrong, as they''ll gobble up whitespace. istreambuf_iterators will count everything.

Share this post


Link to post
Share on other sites

  • Advertisement