gocan76
gocan76

Reputation: 39

writing into file (std::ofstream) in a loop writes last line only

I'm using this code to extract certain part of each line of a text file:

std::ifstream file( "infile.txt" );
std::string in1, out1;
int blockNumber = 0;

while( getline( file, in1 ) ) 
{   
    int n = 0;
    int i = 0;

    while( i <= blockNumber )
    {   
        n = in1.find_first_of("(", n + 1); 
        i++;
    }   
    out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );  
    ofstream fmatch ("solo_matches.txt",ios::out);
    fmatch.close();
    fmatch.open("solo_matches.txt");
    fmatch << out1;
    fmatch.close();
} 

But when I run the code, the result is not as I expect it to be. Only the last string is being written to the file. If I use this instead:

 std::cout << out1 << std::endl;

I get the exact output I need. I do not understand what is the difference.

Upvotes: 0

Views: 15698

Answers (3)

cpp
cpp

Reputation: 3801

Move file open and file close operations outside while loop:

#include<iostream>
#include<fstream>

int main()
{
    std::ifstream file( "infile.txt" );
    std::string in1, out1;
    int blockNumber = 0;
    std::ofstream fmatch ("solo_matches.txt",std::ios::out);

    while( getline( file, in1 ) ) 
    {   
        int n = 0;
        int i = 0;

        while( i <= blockNumber )
        {   
            n = in1.find_first_of("(", n + 1); 
            i++;
        }   
        out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) );  
        //fmatch.close();  //you don't need this
        //fmatch.open("solo_matches.txt"); //you don't need this
        std::cout << out1 << std::endl;
        fmatch << out1 << std::endl;
    }   
    fmatch.close();
}

And replace

fmatch << out1;

with

fmatch << out1 << endl;

if you need cout and fmatch agreement.

Upvotes: 2

LihO
LihO

Reputation: 42083

std::ofstream fmatch("solo_matches.txt", ios::out);
fmatch << ...;
fmatch.close();

opens the file, rewrites its content and saves it upon closing the stream. To append the content at the end of the file, you can use ios::app flag:

std::ofstream fmatch("solo_matches.txt", ios::out | ios::app);

or yet even better, instead of reopening the file in every iteration:

while (...) {
    construct ofstream
    write to file
    close ofstream
}

you could do:

construct ofstream
while (...) {
    write to file
}
close ofstream

Also note that this line:

out1 = in1.substr( n + 1, ( in1.find_first_of(")", n) - n - 1) ); 

relies on the correct format of the input, it would be safer to check the return value of find_first_of:

std::size_t pos = in1.find_first_of(")", n);
if (pos != std::string::npos)
{
    out1 = in1.substr( n + 1, pos - n - 1 );
    ...
}

Upvotes: 1

SigTerm
SigTerm

Reputation: 26409

Well, ofstream probably overwrites existing contents every time you open it. I mean, every time you open file, write pointer will be placed at the begninning, so even without ios::trunc flag new data written into that file will overwrite existing contents.

To solve the problem, stop reopening ofstream twice for every line of text. File open operation can be slow.

Either that, or try using ios::app flag.

Upvotes: 5

Related Questions