473,386 Members | 1,652 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

fstream ?


Before I resort to the "fopen" family, can some-one please direct me to a
tutorial on the net about the "fstream" family.

I've gone through about 10 references and they're all complete bullshit. I'm
trying to find simple answers to simple questions.

What exactly does the constructor do? How does the whole eof thing work?
-JKop
Jul 22 '05 #1
16 1875
JKop <NU**@NULL.NULL> writes:
Before I resort to the "fopen" family, can some-one please direct me to a
tutorial on the net about the "fstream" family.
Not a tutorial but a reference, maybe it helps:
http://www.cppreference.com/cppio.html
I've gone through about 10 references and they're all complete bullshit. I'm
trying to find simple answers to simple questions.

What exactly does the constructor do? How does the whole eof thing work?


See the reference.

HTH && Kind regrads,
Nicolas

--
| Nicolas Pavlidis | Elvis Presly: |\ |__ |
| Student of SE & KM | "Into the goto" | \|__| |
| pa****@sbox.tugraz.at | ICQ #320057056 | |
|-------------------University of Technology, Graz----------------|
Jul 22 '05 #2
http://www.cppreference.com/cppio.html

Thanks, but that's right at the top of my "bullshit" list.
-JKop
Jul 22 '05 #3
The eof flag is set after an attempt to read past the end. It won't be set
after opening a file of size 0.

Fraser.
"JKop"

Before I resort to the "fopen" family, can some-one please direct me to a
tutorial on the net about the "fstream" family.

I've gone through about 10 references and they're all complete bullshit. I'm trying to find simple answers to simple questions.

What exactly does the constructor do? How does the whole eof thing work?
-JKop

Jul 22 '05 #4
JKop wrote:

Before I resort to the "fopen" family, can some-one please direct me to a
tutorial on the net about the "fstream" family.

I've gone through about 10 references and they're all complete bullshit. I'm
trying to find simple answers to simple questions.
And the simple answers are:
The 'fstream' family works exactly like the 2 objects you already are
familiar with: cin, cout

The only difference is: cin and cout are predefined objects, while you
have to create the file-stream objects on your own.

What exactly does the constructor do?
Creating the stream object. Depending on which constructor you use exactly,
the constructor may also open the file and connect the stream with it. The
stream is then immediatly ready to be read from or write to.

How does the whole eof thing work?


eof() works different in C or C++, then it does in a lot of other
languages. In C or C++ the runtime system does not try to tell the
future. As a consequence, eof returns true only if you try *and* failed
to read past the end of the stream.
So eof() is typically used to figure out, why a previous read operation
has failed. If it was because eof() then everything is ok, the file
could have been read correctly till the end.

As an example, study this code snippet, which
reads a text file line by line and copies the
read line into a new file (just to do something
with the data)

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
ifstream InFile( "C:\\test.dat" ); // ifstream: input file stream
ofstream OutFile( "C:\\Copy.dat" ); // ofstream: output file stream

if( !InFile.is_open() ) {
cout << "Could not open input file" << endl;
return EXIT_FAILURE;
}

if( !OutFile.is_open() ) {
cout << "Could not open output file" << endl;
return EXIT_FAILURE;
}

string InLine;

while( getline( InFile, InLine ) )
OutFile << InLine;

if( !InFile.eof() )
cout << "Error during read from file" << endl;
}

Note also the typical read loop:

while( data_can_be_read ) {
process data
}

// figure out why the loop terminated.
// if it was because eof, everything is fine
if( !eof() )
Process error during read
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #5

"Fraser Ross" <fraserATmembers.v21.co.unitedkingdom> wrote in message
news:41******@news.greennet.net...
The eof flag is set after an attempt to read past the end. It won't be set after opening a file of size 0.

Fraser.


int i;
file >> i;

This may successfully read an integer AND set the end of file. If the
integer is the very last thing in the file then the end of file will be set
because you have to read past the end of file to determine that the integer
has been fully read. But if there is a space after the last integer then
reading that space will tell you that the integer has been fully read and
end of file will not be set.

Same applies to getline and other similar read functions that have to read
to some terminator.

John
Jul 22 '05 #6

Thanks Karl.

Here's the gist of what I'm trying to do at the moment: Let's say I have a
file "mammals.txt" and it contains:

cat
dog
ape
monkey
horse
pig

What I want to do is remove a certain line, let's say "horse", so that after
the program runs, "mammals.txt" will look like so:

cat
dog
ape
monkey
pig

Here's what I'm doing so far:

std::ifstream mammal_file( "mammal.txt" );

if ( !mammal_file.is_open() )
{
std::cout << "ERROR: Unable to open \"mammal.txt\"\n";
throw AnException();
}

//The file is now open
std::string one_line;
What I'm intending to do is copy all the lines into a new *output* file
stream, except "horse", and then overwrite the original. Would you be able
to provide any tips at all please?
-JKop
Jul 22 '05 #7
JKop wrote:


What I'm intending to do is copy all the lines into a new *output* file
stream, except "horse", and then overwrite the original. Would you be able
to provide any tips at all please?


Sure.

You are on the right track. When dealing with text files (except in some
rare circumstances), then the only possible way to modify that file is
be writing a new one and while writing that file apply all the intended
modifications. The only exception is when the replacement takes up the
same amount of bytes as the original, then you can simply seek to the
position and overwrite. But those cases are rare.

The next thing you should think about is:
How do I read. I mean: Which functionality do I use.
In your case you have 2 choices

you could eg.

std::string InWord;
InFile >> InWord;

This will work in your case, since each line contains only a single word.
So the basic loop would look like this

...
while( mammal_file >> InWord ) {
if( InWord != "horse" )
OutFile << InWord << "\n";
}
...

But I often feel that a different approach is simpler. What is
the problem? The problem comes if the file format gets more complicated,
saying you have 3 words on each line and there have to be exactly 3 words
on each line or otherwise the record (the line) is in error. So how to do this?
In cases like this it is often simpler to use getline (as I did in the
previous post). You use getline to read in the whole line as a single string
and then use eg. string functions to seperate that total string into the
words. Or you could use a stringstream to do the same.
So why is that often simpler. Think of the error case. By using getline
you have read the whole record, so if you figure out that that record
is bogous you don't need to do anything special with the input stream. You
just don't do anything with the bogus record and continue reading (and
emit an error message).
But in the read loop using >>?
Well, first of all you need to detect that the line is in error. >> ignores
line breaks because they are considered as white space. So detecting that
the number of words per line is wrong isn't that simple. Even then, lets say
the file format asks for a number, but in the file there is a text string "abc".
will fail for obvious reasons. But what then? In order to continue you still need to read until the end of that record is read (the line break) for finding
the start of the next record. With the getline-version this is done all automatically.

But there is one (minor) point with getline. getline reads *and* includes the terminator
(in this case '\n'). So often one needs to get rid of that terminator are at least
deal with it. In your specific case, that would eg. be

while( getline( mammal_file, one_line ) ) {
if( one_line != "horse\n" )
OutFile << one_line;
}

Note: In the version using >> I had to write a '\n' on my own to the output stream, because has filtered it away. In the getline version I don't have to do that, because getline

has placed a '\n' in one_line as last character. That is: if there was one in the file.
The last line in the file may or may not contain a terminating '\n'.

So much for the thoughts about how to get at the file content.
Back to your program.
Open the output file and write to it whatever loop you want to choose.
Once you have finished, all that is left is

* delete the original file
you will want to use function remove() from <cstdio> for that
* rename the newly created file to the original file name
you will want to use function rename() from <cstdio> for that

It is a good idea to actually close the streams before the deletion and
renaming takes place.

As for: How to name that temporary file.
Often just a variation of the input file name is used. If the file system
supports file extensions, then it is often the name of the input file with
a different extension. But there is a second solution. As a leftover from
C there is a function called tmpnam, which generates a filename to be guaranteed
to not collide with any other file name in the directory. But look up the documentation
for that function. Often there are some tricky interactions with environment variables.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #8

Here's how it's going so far:

#include <fstream>
#include <string>

int main()
{
std::ifstream mammals_file( "mammals.txt" );

if ( !mammals_file.is_open() )
{
std::cout << "ERROR: Unable to open \"mammals.txt\"\n";
return -1;
}

//The file is now open

{
std::ofstream out_file;

std::string one_line;

do
{
std::getline(mammals_file, one_line);

if ( !CompareWithoutRegardToCaseX( "horse", one_line.c_str() )
) out_file << one_line << '\n'; //Should I have that '\n' there?
}
while ( !mammals_file.eof() );

//Now save the file, overwriting the original, but how . . . ?
}
}
Any thoughts?
-JKop
Jul 22 '05 #9

Thanks.

I'd written a reply and then two seconds later I wrote another
* delete the original file
you will want to use function remove() from <cstdio> for that
* rename the newly created file to the original file name
you will want to use function rename() from <cstdio> for that


I was wondering if I'd have to name the file in the first place? Is there
anyway to just have it reside in memory, and then at my discretion save it
as a file?

One thing also, I'll have to use "getline" because there could be spaces on
the lines in these files.
-JKop

Jul 22 '05 #10
JKop wrote:

Here's how it's going so far:

#include <fstream>
#include <string>

int main()
{
std::ifstream mammals_file( "mammals.txt" );

if ( !mammals_file.is_open() )
{
std::cout << "ERROR: Unable to open \"mammals.txt\"\n";
return -1;
}

//The file is now open

{
std::ofstream out_file;

You want to pass a file name to the ofstream constructor, such that it
opens the file for you.
std::string one_line;

do
{
std::getline(mammals_file, one_line);

if ( !CompareWithoutRegardToCaseX( "horse", one_line.c_str() )
) out_file << one_line << '\n'; //Should I have that '\n' there?
You used getline. So getline will include the terminator '\n' in the read
string. There is however one potential pitfall, the last line in the file
may not be terminated with '\n', thus the string will not contain it.

Best is often: read with getline, and look at the last character in the string.
If it is a '\n', discard it.

}
while ( !mammals_file.eof() );

//Now save the file, overwriting the original, but how . . . ?
delete original file with remove()
rename written file to original file name using rename()
out_file << one_line }
}

Any thoughts?

-JKop

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #11
JKop wrote:

Thanks.

I'd written a reply and then two seconds later I wrote another
* delete the original file
you will want to use function remove() from <cstdio> for that
* rename the newly created file to the original file name
you will want to use function rename() from <cstdio> for that
I was wondering if I'd have to name the file in the first place? Is there
anyway to just have it reside in memory, and then at my discretion save it
as a file?


std::vector<std::string> will happily store all the strings until
you are ready to

* close the original file
* open the same file for output (which will automatically truncate it
to 0 size)
* write the vector content to it

But note: In a high secure environment that would not be acceptable.
During the time period of opening the file for writing and the actual
finishing of writing, the data exist in memory only. If the computer
crashes during that time (eg. power outage) the data is lost forever.

Using the other version of writing to a temporary and then deleting/renaming
ensures that there is always one complete copy of the whole data set on
the hard disk.

One thing also, I'll have to use "getline" because there could be spaces on
the lines in these files.
Oh. I wanted to mention this, but somehow I forgot :-)

-JKop

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #12

"Karl Heinz Buchegger" <kb******@gascad.at> wrote in message
news:41***************@gascad.at...

Best is often: read with getline, and look at the last character in the string. If it is a '\n', discard it.


I've got a question on comparing a char against '\n'. Since on some
systems, '\n' is represented by #13#10 (a CR/LF pair), what happens when you
compare a char with it? Is there some internal mechanism that actually
compares two bytes instead of just one?

-Howard
Jul 22 '05 #13

"Howard" <al*****@hotmail.com> wrote in message news:d0X6d.460930$OB3.267267@bgtnsc05-

I've got a question on comparing a char against '\n'. Since on some
systems, '\n' is represented by #13#10 (a CR/LF pair), what happens when you
compare a char with it? Is there some internal mechanism that actually
compares two bytes instead of just one?

'\n' is ALWAYS a single character. ALWAYS.

The only thing that happens is that under certain circumstances an output
operation may output two characters when an single '\n' character is
fed to it (and similarly on input).

Jul 22 '05 #14

"Ron Natalie" <ro*@sensor.com> wrote in message
news:41***********************@news.newshosting.co m...

"Howard" <al*****@hotmail.com> wrote in message

news:d0X6d.460930$OB3.267267@bgtnsc05-

I've got a question on comparing a char against '\n'. Since on some
systems, '\n' is represented by #13#10 (a CR/LF pair), what happens when you compare a char with it? Is there some internal mechanism that actually
compares two bytes instead of just one?

'\n' is ALWAYS a single character. ALWAYS.

The only thing that happens is that under certain circumstances an output
operation may output two characters when an single '\n' character is
fed to it (and similarly on input).


Ah, that makes sense. Thanks.
-Howard
Jul 22 '05 #15
>> std::string one_line;

do
{
std::getline(mammals_file, one_line);

if ( !CompareWithoutRegardToCaseX( "horse",
one_line.c_str() )
) out_file << one_line << '\n'; //Should I have that '\n' there?


You used getline. So getline will include the terminator '\n' in the read
string. There is however one potential pitfall, the last line in the file
may not be terminated with '\n', thus the string will not contain it.


No it won't. getline reads the newline but does not include it in the read
string.

john
Jul 22 '05 #16
John Harrison wrote:
std::string one_line;

do
{
std::getline(mammals_file, one_line);

if ( !CompareWithoutRegardToCaseX( "horse",
one_line.c_str() )
) out_file << one_line << '\n'; //Should I have that '\n' there?


You used getline. So getline will include the terminator '\n' in the read
string. There is however one potential pitfall, the last line in the file
may not be terminated with '\n', thus the string will not contain it.


No it won't. getline reads the newline but does not include it in the read
string.


Thanks for correcting.
I somehow always mix this up with fgets() behaviour
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: David Briggs | last post by:
I am using MS VC++ 6.0 with MFC I have a simple class: #include <fstream.h> class Data { public: CString WriteStr(); Data();
3
by: David Blasdell | last post by:
This appears very strange to me, I'm having a problem with a fstream object inside a class which is not being called directly from main (another class calls the class that contains the fstream...
3
by: ratzeel | last post by:
The following snippet code throws an error while compiling on SUN os.. Any idea how to resolve this... #include <iostream.h> #include <fstream.h> #include <math.h> #include <algorithm>...
9
by: Someonekicked | last post by:
In my program, I need to open multiple files, and I wont know till after the program execution how many of them (user will enter that value). So I am using a vector of fstream. I am using fstream...
1
by: MForey | last post by:
I'm attempting to create a program that uses fstream objects to read/write to files. However, it is currently balky at best. The fstream.write call doesn't return an error, but the modified data...
5
by: ehui928 | last post by:
The following program is used to open a file in mode both read and append, but it has a problem that the file can't be opened. #include <iostream> #include <fstream> #include <cstdlib> ...
6
by: wiso | last post by:
My problem is this (from: http://www.cplusplus.com/ref/iostream/fstream/open.html) #include <fstream> using namespace std; int main() { fstream f;
5
by: neowillis | last post by:
code: #include <iostream> #include <fstream> #include <string> using namespace std; int main() {
7
by: Soneji | last post by:
*sigh* Ok, I have two questions. First, my setup: Win-doze XP-SP2; & Dev-C++ 4.9.9.2; I recently started trying to use 'fstream' to work my input/output, and I noticed that using the...
6
by: Gaijinco | last post by:
Should this do something? #include <fstream> #include <string> int main() { std::fstream filestr ("test.txt", std::fstream::in | std::fstream::out); std::string s="";
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.