2

I want to merge two files into one file and when I do it at the end of the my merged file there is an extra blank line, How can I delete it?

file1 contains:

1  2  3

and file2 contains:

4  5  6

the the merged file is like

1  2  3
4  5  6
<------cursor is here

here is my code:

ifstream read1("1.txt");
ifstream read2("2.txt");

ofstream write ("3.txt");

string line;
string line2;

while ( getline ( read1, line, '\n' ) )
{
 if (!line.empty())
  write << line << endl;
}

while ( getline ( read2, line2, '\n' ) )
{
 if (!line2.empty())
  write << line2 << endl;
}

read1.close();
read2.close();
write.close();
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    (1) Don't use `endl` unless you explicitly need the content flushed to disk. And you don't. Use `write << '\n';` (2) You always add a new line at the end of a write operation, so perhaps adding it at another point in the operation is in order. – StoryTeller - Unslander Monica Jun 29 '17 at 12:29
  • I'd prefer to have newlines at the end of all the files (some code / programs seems to deal with this better). Is there a reason you don't want the end of the file on a new line? – crashmstr Jun 29 '17 at 12:31
  • Check for `read2.eof()` before writing newline in the ` write << line2 << endl` – Marek Vitek Jun 29 '17 at 12:35
  • What is with the checks of `empty`? If the string is `emtpy` the read failed and the loop wouldn't execute anyways. – NathanOliver Jun 29 '17 at 12:36
  • 2
    @Marek [Nope!](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – πάντα ῥεῖ Jun 29 '17 at 12:37
  • 1
    @NathanOliver -- you get an empty string when the input contains a blank line. That's not a read failure. – Pete Becker Jun 29 '17 at 12:41
  • @PeteBecker Ah yes. I didn't see empty lines in there example but they might have them. – NathanOliver Jun 29 '17 at 12:42
  • @πάνταῥεῖ and what about situations where original input will contain newline at the end too? – Marek Vitek Jun 29 '17 at 12:43
  • 2
    Formally, both C and C++ **require** writing a newline to the end of a text file. Not having one means that programs that read such a file can fail on some systems. Granted, that's not very common (if I remember correctly, this was an issue for MVS, an ancient mainframe block-oriented file system), but there's usually no good reason for building in non-portabilities. – Pete Becker Jun 29 '17 at 12:50
  • @Marek OP already checks that with `if (!line2.empty())`. No need for `eof()`. – πάντα ῥεῖ Jun 29 '17 at 12:51
  • @PeteBecker And AFAICT, whether the OP's editor displays an empty line at the end, as a result of the trailing newline, is a function of how it renders. `vim` does not for example, but something like Notepad IIRC does. – underscore_d Jun 29 '17 at 12:57
  • @πάνταῥεῖ In fact it is. He has two files containing no newline at the end. When he reads last line there might and might not be newline. Hence the check for EOF as we have to distinguish whether the read ended by EOF or by newline. – Marek Vitek Jun 29 '17 at 13:01
  • Any reasons to read line by line ? – Jarod42 Jun 29 '17 at 13:11

7 Answers7

1

Using the streambuf overload for operator<< we can do:

#include <fstream>

int main()
{
    std::ifstream read1("1.txt");
    std::ifstream read2("2.txt");
    std::ofstream write("3.txt");
    write << read1.rdbuf() << '\n' << read2.rdbuf();
}
wally
  • 10,717
  • 5
  • 39
  • 72
  • Not only it removes any newline, but also adds extra newline – Shakiba Moshiri Jun 29 '17 at 14:01
  • @k-five It seems to me that the objective is to merge two files, not filter out newlines. Granted, the code in question does filter out newlines and then add back its own newlines as separators, but that seems like a means to an end which was not completely working for OP. Clearly the input files are records separated by newlines and the desired output is records separated by newlines. We only require a newline between the files to separate the adjacent records and we're done. – wally Jun 29 '17 at 14:12
  • I thought `if (!line.empty()) write << line << endl; ` is **filter out newlines**. What does it mean? – Shakiba Moshiri Jun 29 '17 at 14:20
  • @k-five Yes, I agree with you that the provided code does filter out newlines. This answer works under the assumption that it was not a requirement, but perhaps an attempt to avoid the newline at the end. The question could be clearer and the sample data doesn't clarify. OP is welcome to choose the answer that works best. – wally Jun 29 '17 at 14:28
0

Before the second while read the first line, write it to the file and then use the while as you do but enter a new line first. Something like this:

getline(read2 , line2, '\n');
if (!line2.empty()) 
   write << line2;

while ( getline ( read2, line2, '\n' ) )
{
 if (!line2.empty())
  write << endl <<line2;
}

This is not exactly what you ask but it should do the trick.

Anoroah
  • 1,987
  • 2
  • 20
  • 31
0

Test for end of input file and don't put additional newline at the end.
Change

write << line2 << endl;

to

{
    write << line2;
    if (!read2.eof()) {write << "\n";}
}

EDIT: I have added curly braces to compensate for your single line IF's. Please try to avoid it in your code. See how George easily fell into that trap.

Marek Vitek
  • 1,573
  • 9
  • 20
0

<< endl will flush the buffer and add a '\n' You can think of it was being equivalent to adding a '\n' at the end, for added simplicity.

If you want to never add a newline just write the code as: ifstream read1("1.txt"); ifstream read2("2.txt");

ofstream write ("3.txt");

string line;
string line2;

while ( getline ( read1, line, '\n' ) )
{
 if (!line.empty())
  write << line;
}

while ( getline ( read2, line2, '\n' ) )
{
 if (!line2.empty())
  write << line2;
}

read1.close();
read2.close();
write.close();

If you wish to write a newline after every line in the fact except the last line of the last file than buffer the thing into a string and write that to the file... not the most efficient option maybe, but good enough:

ifstream read1("1.txt");
ifstream read2("2.txt");

ofstream write ("3.txt");

string line;
string line2;
string buffer
while ( getline ( read1, line, '\n' ) )
{
 if (!line.empty())
  buffer += line;
  buffer += "\n";
}

while ( getline ( read2, line2, '\n' ) )
{
 if (!line2.empty())
        buffer += line2;
        buffer += "\n";
}

//Remove the last char from buffer (the '\n' bothering you)
buffer.substr(0, myString.size()-1)
write << buffer;

read1.close();
read2.close();
write.close();

Marek Vitek's answer is actually better than mine:

ofstream write ("3.txt");

string line;
string line2;

while ( getline ( read1, line, '\n' ) )
{
 if (!line.empty())
  write << line << endl;
}

while ( getline ( read2, line2, '\n' ) )
{
 if (!line2.empty()) {
  write << line2 
 } 
 if(!line2.empty() && !read2.eof() {
  write << line2 << endl;
 } 
}

read1.close();
read2.close();
write.close();
George
  • 3,521
  • 4
  • 30
  • 75
0

How about raw copy:

std::ifstream read1{path1};
read1.unsetf(std::ios_base::skipws);
std::ifstream read2{path2};
read2.unsetf(std::ios_base::skipws);
std::ofstream write{path3};

std::copy(std::istream_iterator<char>(read1),
          std::istream_iterator<char>(),
          std::ostream_iterator<char> (write));

write << '\n'; // extra EOL between file

std::copy(std::istream_iterator<char>(read2),
          std::istream_iterator<char>(),
          std::ostream_iterator<char> (write));
Jarod42
  • 203,559
  • 14
  • 181
  • 302
-1

Another short solution (though I don't know what should be wrong with the final newline in the merged result):

ifstream read1("1.txt");
ifstream read2("2.txt");

ofstream write ("3.txt");

string line;
string line2;

do {
    if (!line.empty())
       write << line << '\n';
} while( getline ( read1, line, '\n' ) )
write.flush();

do {
    if(!line2.empty())
        write << line2;
} while( getline ( read2, line2, '\n' ) && write << `\n`);

read1.close();
read2.close();
write.close();
Jarod42
  • 203,559
  • 14
  • 181
  • 302
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
-1

merge two file that has extra newline

std::ifstream ifs_1( "file1" );
std::ifstream ifs_2( "file2" );

std::ofstream ofs( "file3" );

for( std::string line; std::getline( ifs_1, line ); ){
    if( line != "" ){
        ofs << line << '\n';
    }
}
for( std::string line; std::getline( ifs_2, line ); ){
    if( line != "" ){
        ofs << line << '\n';
    }
}

ifs_1.close();
ifs_2.close();

ofs.close();

test:

cat file1
one
two
--> empty
--> empty

and file2:

cat file2:
three
four
--> empty
--> empty

the output:

cat file3
one
two
three
four
Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44