views:

584

answers:

5

I'm writing a program on a Linux platform that is generating text files that will be viewed on, inevitably, a Windows platform.

Right now, passing std::endl into a ostream generates the CR character only for newlines. Naturally, these text files look wrong in MS Notepad.

1) Is there a way to change std::endl such that it uses CR+LF for newline instead of LF?

2) I know I could write my own custom manipulator, like win_endl, for generating my own newlines, but I use the std::endl symbol in a lot of places, and like many programmers, have a tendency to do the thing that requires the least work possible. Could I simply overload std::endl to produce CR+LF, or is this a dumb idea for maintainability?

NB: I checked out this question, but it's asking about going the other way, and the accepted answer seems rather incomplete.

+2  A: 

std::endl is basicly:

std::cout << "\n" << std::flush;

So just use "\r\n" instead and omit the flush. It's faster that way, too!

From the ostream header file on endl:

This manipulator is often mistakenly used when a simple newline is desired, leading to poor buffering performance.

ebo
If you do that, don't forget to open the stream in binary mode - otherwise, if you ever port this code to Windows, you'll get `\r\r\n` in the output (since `\n` itself will be expanded into `\r\n` for a text stream).
Pavel Minaev
This won't be ported to Windows, I don't think. We probably couldn't handle the licensing. lol
sheepsimulator
+1 - Good info on the endl manipulator. Methinks I will be using it less often now.
sheepsimulator
If your file is in text mode. The character '\n' is translated into a platform specific end of line sequence when you write to the file. And the end of line sequence is translated into '\n' when you read from the file.
Martin York
+1  A: 

You shouldn't use \r\n. Just use \n, but then open the stream in "text" mode, which than will do the conversion for you. You may not care about cross-platform, but this is the official way of doing it.

That way, the same code will spit-out \n on unix, \r\n on windows, and \r on mac.

zumalifeguard
Also, don't use MS Notepad
Cogwheel - Matthew Orlando
The program that generates the text file will *always* be run on a Linux platform, and it won't be run on Win/Mac at all. The machines that read the text file will be running consumer OSes (Windows, Mac, Linux).
sheepsimulator
Did you actually read the question?
mch
The problem is NotePad, as simple as the application is, doesn't respect other newlines. Other platforms default text editors do, so he's being forced to make it `\r\n`, so Windows plays nice as well.
GMan
+1 for reminding me that our customers could be running on Macs. I shouldn't forget about Macs.
sheepsimulator
\r as EOL was used on Mac OS 9, OS X uses \n.
PiotrLegnica
Also, if you have a text file with \n for the line-endings, you can easily view and edit that file if use wordpad, which comes with every windows. You wouldn't do this on your own computer because hopefully you'd have something like notepad++ installed. But if you're running on some arbitrary computer, it's nice to know the wordpad trick.
zumalifeguard
+4  A: 

Opening a file in text mode should cause std::endl to be converted to the appropriate line ending for your platform. Your problem is that newline is appropriate for your platform, but the files you create aren't intended for your platform.

I'm not sure how you plan on overloading or changing endl, and changing its behavior would certainly be surprising for any developers new to your project. I'd recommend switching to win_endl (should be a simple search-and-replace) or maybe switching from a standard ostream to a Boost.Iostreams filtering stream to do the conversion for you.

Josh Kelley
+1 for the Boost.IOStreams solution. More specifically, use a newline_filter: http://www.boost.org/doc/libs/1_40_0/libs/iostreams/doc/index.html?path=4.2.10.1
Éric Malenfant
Would have gone this route (still may if the macro becomes cumbersome to maintain) but we have a goofy system for getting boost pkgs at work, and I would've had to bug someone to go through some rigmarole to get it to my console.
sheepsimulator
+2  A: 

Windows Notepad is pretty much the only Windows program you'll find that doesn't handle LF-only files properly. Almost everything else (including WordPad) handles LF-only files just fine.

This problem is a bug in Notepad.

Greg Hewgill
Our customers will likely just double-click on the file, so we'll be at the mercy of whatever app has registered itself at the time on their machine. Likely the default Notepad on Windows.
sheepsimulator
generate html instead?
ebo
If you must create files with CRLF line endings, run the output file(s) through a filter that is independent of your program itself. You can find this sort of filter easily, look for `unix2dos` or something like that. This will keep this platform-specific logic out of your program.
Greg Hewgill
However, don't forget that Unix programs are generally as unforgiving of reading text files that contain "\r\n" line endings - from my limited experience with Unix, that seems to be a more wide-spread issue (in terms of the number of programs that don't deal well with non-native line endings).
Michael Burr
A: 

Here was my solution to the problem. It's a bit of a mash-up of all the info provided in the answers:

  1. I created a macro in a win_endl.h file for the newline I wanted:

    #define win_endl "\r\n"

  2. Then I did a search-and-replace:

    sheepsimulator@sheep_machine > sed -i 's/std::endl/win_endl' *

And ensured all my files included win_endl.h.

sheepsimulator
This really isn't a solution if you are using text mode, since "\n" is translated into a platform specific end-of-line sequence. On Linux, "\n" does map directly to the LF character. But if you ran this code on Windows, you'd see CR-CR-LF because "\n" maps to CR-LF on Windows.
Brian Neal
This code won't be running on Windows. Please read my original question carefully.
sheepsimulator