Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is it possible to use std::cout for binary output?

39 views
Skip to first unread message

Richard

unread,
Sep 25, 2019, 12:20:38 AM9/25/19
to
[Please do not mail me a copy of your followup]

I'm not talking about printing numbers in base 2.

I have a program that outputs ESC sequences for a terminal. I don't
want Windows to translate '\n' into '\r\n'. If I construct an
ofstream with std::ios_base::binary, then that's what I get. However,
if I try to use std::cout, I always get a stream that's been opened in
text mode and I get \n -> \r\n in the output.

Is there a way to switch std::cout to behave as if I did
std::ofstream(fileName, std::ios_base::binary)?
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Paavo Helde

unread,
Sep 25, 2019, 2:16:30 AM9/25/19
to
On 25.09.2019 7:20, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> I'm not talking about printing numbers in base 2.
>
> I have a program that outputs ESC sequences for a terminal. I don't
> want Windows to translate '\n' into '\r\n'. If I construct an
> ofstream with std::ios_base::binary, then that's what I get. However,
> if I try to use std::cout, I always get a stream that's been opened in
> text mode and I get \n -> \r\n in the output.
>
> Is there a way to switch std::cout to behave as if I did
> std::ofstream(fileName, std::ios_base::binary)?

Sure, this should do the trick:

#include <iostream>
#include <io.h>
#include <fcntl.h>

int main() {
fflush(stdout);
_setmode(_fileno(stdout), _O_BINARY);
std::cout << "\n";
}

This solution is Windows/MSVC-specific, but so is the problem.

Melzzzzz

unread,
Sep 25, 2019, 1:39:12 PM9/25/19
to
On 2019-09-25, Richard <legaliz...@mail.xmission.com> wrote:
> [Please do not mail me a copy of your followup]
>
> I'm not talking about printing numbers in base 2.
>
> I have a program that outputs ESC sequences for a terminal. I don't
> want Windows to translate '\n' into '\r\n'. If I construct an
> ofstream with std::ios_base::binary, then that's what I get. However,
> if I try to use std::cout, I always get a stream that's been opened in
> text mode and I get \n -> \r\n in the output.
>
> Is there a way to switch std::cout to behave as if I did
> std::ofstream(fileName, std::ios_base::binary)?
Google `write` member function of ostream...

--
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala

Frederick Gotham

unread,
Sep 25, 2019, 1:46:45 PM9/25/19
to
Also check out this:


https://stackoverflow.com/questions/2273330/restore-the-state-of-stdcout-after-manipulating-it


And look at the second answer that uses boost.

Richard

unread,
Sep 25, 2019, 3:02:27 PM9/25/19
to
[Please do not mail me a copy of your followup]

Melzzzzz <Melz...@zzzzz.com> spake the secret code
<TCNiF.384226$Jh2.3...@fx39.am4> thusly:

>On 2019-09-25, Richard <legaliz...@mail.xmission.com> wrote:
>> [Please do not mail me a copy of your followup]
>>
>> I'm not talking about printing numbers in base 2.
>>
>> I have a program that outputs ESC sequences for a terminal. I don't
>> want Windows to translate '\n' into '\r\n'. If I construct an
>> ofstream with std::ios_base::binary, then that's what I get. However,
>> if I try to use std::cout, I always get a stream that's been opened in
>> text mode and I get \n -> \r\n in the output.
>>
>> Is there a way to switch std::cout to behave as if I did
>> std::ofstream(fileName, std::ios_base::binary)?
>Google `write` member function of ostream...

Unfortunately that doesn't work. Neither does the put method. You
still get EOL translation.

Richard

unread,
Sep 25, 2019, 3:03:49 PM9/25/19
to
[Please do not mail me a copy of your followup]

Frederick Gotham <cauldwel...@gmail.com> spake the secret code
<1f7e47cd-e479-4478...@googlegroups.com> thusly:
Yep, already looked there. The binary/text state of the stream isn't
something you can change with a iostream manipulator and isn't
something you can change with these flags.

Jorgen Grahn

unread,
Sep 25, 2019, 3:13:43 PM9/25/19
to
Is it, really? The language is aware of the text/binary distinction,
so I bet it specifies which one std::cout is, and whether you can
portably do anything about it.

(Personally I'm happy to be Unix-specific in my code, so I haven't had
reason to look into this in detail. In my context, text and binary
are the same thing.)

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

James Kuyper

unread,
Sep 25, 2019, 4:09:32 PM9/25/19
to
On 9/25/19 3:13 PM, Jorgen Grahn wrote:
> On Wed, 2019-09-25, Paavo Helde wrote:
>> On 25.09.2019 7:20, Richard wrote:
>>> [Please do not mail me a copy of your followup]
>>>
>>> I'm not talking about printing numbers in base 2.
>>>
>>> I have a program that outputs ESC sequences for a terminal. I don't
>>> want Windows to translate '\n' into '\r\n'. If I construct an
>>> ofstream with std::ios_base::binary, then that's what I get. However,
>>> if I try to use std::cout, I always get a stream that's been opened in
>>> text mode and I get \n -> \r\n in the output.
>>>
>>> Is there a way to switch std::cout to behave as if I did
>>> std::ofstream(fileName, std::ios_base::binary)?
>>
>> Sure, this should do the trick:
>>
>> #include <iostream>
>> #include <io.h>
>> #include <fcntl.h>
>>
>> int main() {
>> fflush(stdout);
>> _setmode(_fileno(stdout), _O_BINARY);
>> std::cout << "\n";
>> }
>>
>> This solution is Windows/MSVC-specific, but so is the problem.
>
> Is it, really? The language is aware of the text/binary distinction,
> so I bet it specifies which one std::cout is, and whether you can
> portably do anything about it.

"The object cout controls output to a stream buffer associated with the
object stdout, declared in
<cstdio> (30.11.1)." (30.4.3p3)

"1 The contents and meaning of the header <cstdio> are the same as the C
standard library header <stdio.h>." (30.11.1p1)

" stderr
stdin
stdout
which are expressions of type ‘‘pointer to FILE’’ that point to the FILE
objects associated, respectively, with the standard error, input, and
output streams." (C2011 7.21.1p3).

The C standard defines two functions that can set the mode of a stream:
fopen() and freopen() (Annex K adds fopen_s() and freopen_s()). Since
stdout starts out already open, freopen() is your only option. For
freopen(filename, mode, stream), section 7.21.5.4 of the C standard says:

"2 The freopen function opens the file whose name is the string pointed
to by filename and associates the stream pointed to by stream with it.
The mode argument is used just as in the fopen function. 272)
3 If filename is a null pointer, the freopen function attempts to change
the mode of the stream to that specified by mode, as if the name of the
file currently associated with the stream had been used. It is
implementation-defined which changes of mode are permitted (if any), and
under what circumstances."

Paavo Helde

unread,
Sep 25, 2019, 5:15:48 PM9/25/19
to
On 25.09.2019 22:13, Jorgen Grahn wrote:
> On Wed, 2019-09-25, Paavo Helde wrote:
>> On 25.09.2019 7:20, Richard wrote:
>>> [Please do not mail me a copy of your followup]
>>>
>>> I'm not talking about printing numbers in base 2.
>>>
>>> I have a program that outputs ESC sequences for a terminal. I don't
>>> want Windows to translate '\n' into '\r\n'. If I construct an
>>> ofstream with std::ios_base::binary, then that's what I get. However,
>>> if I try to use std::cout, I always get a stream that's been opened in
>>> text mode and I get \n -> \r\n in the output.
>>>
>>> Is there a way to switch std::cout to behave as if I did
>>> std::ofstream(fileName, std::ios_base::binary)?
>>
>> Sure, this should do the trick:
>>
>> #include <iostream>
>> #include <io.h>
>> #include <fcntl.h>
>>
>> int main() {
>> fflush(stdout);
>> _setmode(_fileno(stdout), _O_BINARY);
>> std::cout << "\n";
>> }
>>
>> This solution is Windows/MSVC-specific, but so is the problem.
>
> Is it, really? The language is aware of the text/binary distinction,
> so I bet it specifies which one std::cout is, and whether you can
> portably do anything about it.

By default all streams are text, you need to add special
ios_base::binary flag when opening them to get binary.

The question is if there is a standard way to reopen std::cout in binary
mode, and my googling attempts seem to say "no". I suspect this might
not even be technically possible on some older OS-es with rigid file
formats.

>
> (Personally I'm happy to be Unix-specific in my code, so I haven't had
> reason to look into this in detail. In my context, text and binary
> are the same thing.)

This sounds like a confession you have written an amount of non-portable
code yourself over the years.

Paavo Helde

unread,
Sep 25, 2019, 5:27:05 PM9/25/19
to
On 25.09.2019 23:09, James Kuyper wrote:
> 3 If filename is a null pointer, the freopen function attempts to change
> the mode of the stream to that specified by mode, as if the name of the
> file currently associated with the stream had been used. It is
> implementation-defined which changes of mode are permitted (if any), and
> under what circumstances."

Alas, this does not work under MSVC. If passed path=nullptr, freopen()
fails with error "Bad file descriptor".



Keith Thompson

unread,
Sep 25, 2019, 6:32:16 PM9/25/19
to
That's not surprising. That paragraph wasn't added until C99. In C90,
calling freopen() with a null pointer for the filename had undefined
behavior.

On the other hand, C++11 refers to the C99 standard, so freopen() should
behave as specified by C99. But that still doesn't require all mode
changes to be supported.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Jorgen Grahn

unread,
Sep 26, 2019, 7:19:31 AM9/26/19
to
On Wed, 2019-09-25, Paavo Helde wrote:
> On 25.09.2019 22:13, Jorgen Grahn wrote:
...
>> (Personally I'm happy to be Unix-specific in my code, so I haven't had
>> reason to look into this in detail. In my context, text and binary
>> are the same thing.)
>
> This sounds like a confession you have written an amount of non-portable
> code yourself over the years.

"I'm happy to be Unix-specific in my code" is such a confession, yes.

I care about some things (such as portability between architectures
and Unix dialects) but I don't care about Windows or other platforms I
don't use, unless someone pays me.

Scott Lurndal

unread,
Sep 26, 2019, 9:20:49 AM9/26/19
to
That doesn't follow.

Unix (more specifically POSIX) code is very portable, by intent.

Personally, all the C and C++ code I've written is portable between pretty much
every Unix-like operating system.

Scott Lurndal

unread,
Sep 26, 2019, 9:21:21 AM9/26/19
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
>On Wed, 2019-09-25, Paavo Helde wrote:
>> On 25.09.2019 22:13, Jorgen Grahn wrote:
>...
>>> (Personally I'm happy to be Unix-specific in my code, so I haven't had
>>> reason to look into this in detail. In my context, text and binary
>>> are the same thing.)
>>
>> This sounds like a confession you have written an amount of non-portable
>> code yourself over the years.
>
>"I'm happy to be Unix-specific in my code" is such a confession, yes.
>
>I care about some things (such as portability between architectures
>and Unix dialects) but I don't care about Windows or other platforms I
>don't use, unless someone pays me.

Hear! Hear!

Andy they couldn't pay me enough to write code for Windows.

James Kuyper

unread,
Sep 26, 2019, 10:19:50 AM9/26/19
to
On Thursday, September 26, 2019 at 9:20:49 AM UTC-4, Scott Lurndal wrote:
> Paavo Helde <myfir...@osa.pri.ee> writes:
> >On 25.09.2019 22:13, Jorgen Grahn wrote:
>
> >
> >>
> >> (Personally I'm happy to be Unix-specific in my code, so I haven't had
> >> reason to look into this in detail. In my context, text and binary
> >> are the same thing.)
> >
> >This sounds like a confession you have written an amount of non-portable
> >code yourself over the years.
> >
>
> That doesn't follow.
>
> Unix (more specifically POSIX) code is very portable, by intent.

How portable is it to non-POSIX systems?

Richard

unread,
Sep 26, 2019, 5:28:27 PM9/26/19
to
[Please do not mail me a copy of your followup]

James Kuyper <james...@alumni.caltech.edu> spake the secret code
<f764b2f7-f151-4882...@googlegroups.com> thusly:
In particular, C and C++ don't assume POSIX, even though they
originated from POSIX-like environments.

James Kuyper

unread,
Sep 26, 2019, 6:24:28 PM9/26/19
to
On 9/26/19 5:28 PM, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> James Kuyper <james...@alumni.caltech.edu> spake the secret code
> <f764b2f7-f151-4882...@googlegroups.com> thusly:
>
>> On Thursday, September 26, 2019 at 9:20:49 AM UTC-4, Scott Lurndal wrote:
>>> Paavo Helde <myfir...@osa.pri.ee> writes:
>>>> On 25.09.2019 22:13, Jorgen Grahn wrote:
>>>
>>>>
>>>>>
>>>>> (Personally I'm happy to be Unix-specific in my code, so I haven't had
>>>>> reason to look into this in detail. In my context, text and binary
>>>>> are the same thing.)
>>>>
>>>> This sounds like a confession you have written an amount of non-portable
>>>> code yourself over the years.
>>>>
>>>
>>> That doesn't follow.
>>>
>>> Unix (more specifically POSIX) code is very portable, by intent.
>>
>> How portable is it to non-POSIX systems?
>
> In particular, C and C++ don't assume POSIX, even though they
> originated from POSIX-like environments.

The C standard only mentions POSIX once, in the Bibliography section.
However, by my count, the C++ standard refers to POSIX 92 times. As far
as I can tell (I didn't check closely), nothing it says about POSIX is
mandatory, but in several places it encourages non-POSIX implementations
to emulate POSIX behavior to the extent possible.

David Brown

unread,
Sep 27, 2019, 3:03:07 AM9/27/19
to
I'd expect that depends on what the code does. A fair amount of systems
and libraries have POSIX or POSIX-like API's to aid portability (or at
least reduce programmer learning curves), even in non POSIX systems.
I've seen embedded network stacks with POSIX-like socket interfaces
while running on bare metal, and RTOS's with POSIX-like API's for
multi-threading. Clearly these only implement a subset of POSIX
features, but if they cover your code's needs, you have portability.

0 new messages