 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
JKop Guest
|
Posted: Tue Sep 28, 2004 10:13 am Post subject: 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
|
|
| Back to top |
|
 |
Nicolas Pavlidis Guest
|
Posted: Tue Sep 28, 2004 10:39 am Post subject: Re: fstream ? |
|
|
JKop <NULL (AT) NULL (DOT) NULL> writes:
| Quote: | 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
| Quote: | 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
--
| Quote: | Nicolas Pavlidis | Elvis Presly: | |__ |
Student of SE & KM | "Into the goto" | |__| |
[email]pavnic (AT) sbox (DOT) tugraz.at[/email] | ICQ #320057056 | |
-------------------University of Technology, Graz----------------|
|
|
|
| Back to top |
|
 |
JKop Guest
|
Posted: Tue Sep 28, 2004 11:14 am Post subject: Re: fstream ? |
|
|
Thanks, but that's right at the top of my "bullshit" list.
-JKop
|
|
| Back to top |
|
 |
Fraser Ross Guest
|
Posted: Tue Sep 28, 2004 11:57 am Post subject: Re: fstream ? |
|
|
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"
| Quote: |
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
|
|
|
| Back to top |
|
 |
John Harrison Guest
|
Posted: Tue Sep 28, 2004 12:21 pm Post subject: Re: fstream ? |
|
|
"Fraser Ross" <fraserATmembers.v21.co.unitedkingdom> wrote
| Quote: | 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
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Tue Sep 28, 2004 12:50 pm Post subject: Re: fstream ? |
|
|
JKop wrote:
| Quote: |
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.
| Quote: |
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.
| Quote: | 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
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
JKop Guest
|
Posted: Thu Sep 30, 2004 11:22 am Post subject: Re: fstream ? |
|
|
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
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Thu Sep 30, 2004 11:58 am Post subject: Re: fstream ? |
|
|
JKop wrote:
| Quote: |
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".
| Quote: | 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 != "horsen" )
OutFile << one_line;
}
Note: In the version using >> I had to write a 'n' on my own to the output stream, because
| Quote: | 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
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
JKop Guest
|
Posted: Thu Sep 30, 2004 12:00 pm Post subject: Re: fstream ? |
|
|
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
|
|
| Back to top |
|
 |
JKop Guest
|
Posted: Thu Sep 30, 2004 12:10 pm Post subject: Re: fstream ? |
|
|
Thanks.
I'd written a reply and then two seconds later I wrote another
| Quote: | * 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
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Thu Sep 30, 2004 12:14 pm Post subject: Re: fstream ? |
|
|
JKop wrote:
| Quote: |
Here's how it's going so far:
#include
#include
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.
| Quote: | 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.
| Quote: | }
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
| Quote: | }
}
Any thoughts?
-JKop
|
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Thu Sep 30, 2004 12:21 pm Post subject: Re: fstream ? |
|
|
JKop wrote:
| Quote: |
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.
| Quote: |
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 :-)
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
Howard Guest
|
Posted: Thu Sep 30, 2004 5:04 pm Post subject: Re: fstream ? |
|
|
"Karl Heinz Buchegger" <kbuchegg (AT) gascad (DOT) at> wrote
| Quote: |
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
|
|
| Back to top |
|
 |
Ron Natalie Guest
|
Posted: Thu Sep 30, 2004 5:43 pm Post subject: Re: fstream ? |
|
|
"Howard" <alicebt (AT) hotmail (DOT) com> wrote
| Quote: |
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).
|
|
| Back to top |
|
 |
Howard Guest
|
Posted: Thu Sep 30, 2004 5:46 pm Post subject: Re: fstream ? |
|
|
"Ron Natalie" <ron (AT) sensor (DOT) com> wrote
| Quote: |
"Howard" <alicebt (AT) hotmail (DOT) com> wrote
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
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|