469,299 Members | 2,035 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,299 developers. It's quick & easy.

binary output to stdout in Windows

I have a C program that writes binary output to stdout,
which works fine in Unix/Linux. But when someone else
compiled and ran it in Windows, every time the program
emitted a 0x0A, Windows interpreted it as an lf, and
preceded it with a spurious 0x0D cr. Cute. Is there
some way I can freopen() (so to speak) stdout in binary
mode under Windows so that doesn't happen? Hopefully,
the fix would be portable, so it could compile and
execute under Unix, too, with no ill effects.
Thanks,
--
John Forkosh ( mailto: j@f.com where j=john and f=forkosh )
Nov 14 '05 #1
8 5567
try _setmode()

Search _setmode (third hit) in

http://msdn.microsoft.com/library

with respect,
Toni Uusitalo

"John Forkosh" <jo**@SeeSigForAddress.invalid.com> wrote in message
news:c0**********@reader2.panix.com...
I have a C program that writes binary output to stdout,
which works fine in Unix/Linux. But when someone else
compiled and ran it in Windows, every time the program
emitted a 0x0A, Windows interpreted it as an lf, and
preceded it with a spurious 0x0D cr. Cute. Is there
some way I can freopen() (so to speak) stdout in binary
mode under Windows so that doesn't happen? Hopefully,
the fix would be portable, so it could compile and
execute under Unix, too, with no ill effects.
Thanks,
--
John Forkosh ( mailto: j@f.com where j=john and f=forkosh )

Nov 14 '05 #2
In article <news:c0**********@reader2.panix.com>
John Forkosh <jo**@SeeSigForAddress.invalid.com> writes:
I have a C program that writes binary output to stdout,
which works fine in Unix/Linux. But when someone else
compiled and ran it in Windows, every time the program
emitted a 0x0A, Windows interpreted it as an lf, and
preceded it with a spurious 0x0D cr. Cute. Is there
some way I can freopen() (so to speak) stdout in binary
mode under Windows so that doesn't happen? Hopefully,
the fix would be portable, so it could compile and
execute under Unix, too, with no ill effects.


In C99 there is a way (I think -- it is not in my draft; I should
probably buy the actual C99 .pdf file):

FILE *result;
...
result = freopen(NULL, "wb", stdout);

Here, "result" should compare equal to stdout on success, and NULL
on failure.

Unfortunately, passing NULL to freopen() in C89 results in undefined
behavior -- and in many real implementations, a crash and/or
core-dump.

You might use the theoretically-portable freopen() method as your
"standard" technique that is rarely used today but more frequently
tomorrow, and meanwhile resort to some nonstandard method(s) for
existing implementations. (I have no idea what those might be
beyond something spelled something like "setmode".)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #3
Chris Torek <no****@torek.net> wrote:
John Forkosh <jo**@SeeSigForAddress.invalid.com> writes:
<snip>
[How to transparently write binary data to stdout.]
In C99 there is a way (I think -- it is not in my draft; I should
probably buy the actual C99 .pdf file):

FILE *result;
...
result = freopen(NULL, "wb", stdout);

Here, "result" should compare equal to stdout on success, and NULL
on failure.

Unfortunately, passing NULL to freopen() in C89 results in undefined
behavior -- and in many real implementations, a crash and/or
core-dump.


Unfortunately, even in C99 this is not as portable as
one might think (or wish):

C99 7.19.5.4#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.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^

FWIW, on at least one popular platform this C99 program:

#include <stdio.h>
int main( void )
{
FILE *fp = freopen( NULL, "wb", stdout );
fputs( fp ? "Ok.\n" : "Dang!\n", stderr );
return 0;
}

prints 'Dang!' and leaves stdout closed! :-(

Conclusion: the only portable way (I can think of)
to write binary data from a C program is writing it
to a file explicitly fopen()ed in "[w|a][+]b" mode.

<snip>

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc : http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
acllc-c++ faq : http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #4

"Chris Torek" <no****@torek.net> wrote in message
news:c0*********@enews3.newsguy.com...
In article <news:c0**********@reader2.panix.com>
John Forkosh <jo**@SeeSigForAddress.invalid.com> writes:
I have a C program that writes binary output to stdout,
which works fine in Unix/Linux. But when someone else
compiled and ran it in Windows, every time the program
emitted a 0x0A, Windows interpreted it as an lf, and
preceded it with a spurious 0x0D cr. Cute. Is there
some way I can freopen() (so to speak) stdout in binary
mode under Windows so that doesn't happen? Hopefully,
the fix would be portable, so it could compile and
execute under Unix, too, with no ill effects.
You might use the theoretically-portable freopen() method as your
"standard" technique that is rarely used today but more frequently
tomorrow, and meanwhile resort to some nonstandard method(s) for
existing implementations. (I have no idea what those might be
beyond something spelled something like "setmode".)
--


I didn't know freopen could be used to change file mode in the newer
standard.
But I guess this doesn't help the OP in the present time. Luckily all
programmers
love to write tons of #ifdefs ;-)

I'll use "theoretically-portable" phrase next to "theoretical performance"
numbers next time I advertise some piece of s**tware I've written ;-)

with respect,
Toni Uusitalo

Nov 14 '05 #5
Toni Uusitalo <to**************@pandot.nu> wrote:
: "John Forkosh" wrote:
: > I have a C program that writes binary output to stdout,
: > which works fine in Unix/Linux. But when someone else
: > compiled and ran it in Windows, every time the program
: > emitted a 0x0A, Windows interpreted it as an lf, and
: > preceded it with a spurious 0x0D cr. Cute. Is there
: > some way I can freopen() (so to speak) stdout in binary
: > mode under Windows so that doesn't happen? Hopefully,
: > the fix would be portable, so it could compile and
: > execute under Unix, too, with no ill effects. Thanks,

: try _setmode()
: Search _setmode (third hit) in
: http://msdn.microsoft.com/library
: --
: Toni Uusitalo

Thanks, Toni. As suggested, I modified code to include,
essentially,
if ( _setmode(_fileno(stdout), _O_BINARY)
== -1 ) ; /* error */
guarded by an ugly #ifdef to determine whether or not
it's a Windows compilation.
Mailed fix to user who replied that he hasn't had time
to try it yet, but is "sure it will work" -- poor, naive soul!
I'll post another short followup when outcome is known,
especially if my cynical, Murphy's Law attitude bears its
usual fruits.

Chris Torek wrote:
: In C99 there is a way (I think -- it is not in my draft; I should
: probably buy the actual C99 .pdf file):
: FILE *result;
: result = freopen(NULL, "wb", stdout);
: Here, "result" should compare equal to stdout on success, and NULL
: on failure. Unfortunately, passing NULL to freopen() in C89 results
: in undefined behavior -- and in many real implementations, a crash
: and/or core-dump.
: You might use the theoretically-portable freopen() method as your
: "standard" technique that is rarely used today but more frequently
: tomorrow, and meanwhile resort to some nonstandard method(s) for
: existing implementations. (I have no idea what those might be
: beyond something spelled something like "setmode".)
: --
: Chris Torek, Wind River Systems, http://web.torek.net/torek/index.html

-- and --

Irrwahn Grausewitz <ir*******@freenet.de> wrote:
: Unfortunately, even in C99 this is not as portable as
: one might think (or wish):
: C99 7.19.5.4#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.
: ^^^^^^^^^^^
: FWIW, on at least one popular platform this C99 program:
: #include <stdio.h>
: int main( void )
: { FILE *fp = freopen( NULL, "wb", stdout );
: fputs( fp ? "Ok.\n" : "Dang!\n", stderr );
: return 0; }
: prints 'Dang!' and leaves stdout closed! :-(
: Conclusion: the only portable way (I can think of)
: to write binary data from a C program is writing it
: to a file explicitly fopen()ed in "[w|a][+]b" mode.
: --
: Irrwahn Grausewitz (ir*******@freenet.de)

Thanks Chris and Irrwahn. For the time being, at least,
I used Toni's suggestion since a non-portable solution
is better than a portable non-solution.
Can't write to a file because program is used as a
cgi, and therefore has to emit bytes directly to stdout
so Apache (or whatever) can pick them up.

Thanks again for help, guys,
--
John Forkosh ( mailto: j@f.com where j=john and f=forkosh )
Nov 14 '05 #6
In <ac********************************@4ax.com> Irrwahn Grausewitz <ir*******@freenet.de> writes:
FWIW, on at least one popular platform this C99 program:

#include <stdio.h>
int main( void )
{
FILE *fp = freopen( NULL, "wb", stdout );
fputs( fp ? "Ok.\n" : "Dang!\n", stderr );
return 0;
}

prints 'Dang!' and leaves stdout closed! :-(
If this platform doesn't claim C99-conformance, the program invokes
undefined behaviour, anyway. As Chris mentioned, this is not a C89
feature.
Conclusion: the only portable way (I can think of)
to write binary data from a C program is writing it
to a file explicitly fopen()ed in "[w|a][+]b" mode.


What is preventing a conforming implementation from having an fopen()
that fails for all these modes?

Being a QoI issue, it is reasonable to expect conforming C99
implementations to allow mode changes when freopen() is invoked this way.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #7
In <c0*********@enews3.newsguy.com> Chris Torek <no****@torek.net> writes:
In C99 there is a way (I think -- it is not in my draft; I should
probably buy the actual C99 .pdf file):


For this particular purpose, it is enough to upgrade to the last public
draft, N869:

[#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.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #8
John Forkosh <jo**@SeeSigForAddress.invalid.com> wrote:
: Toni Uusitalo <to**************@pandot.nu> wrote:
: : "John Forkosh" wrote:
: : > I have a C program that writes binary output to stdout,
: : > which works fine in Unix/Linux. But when someone else
: : > compiled and ran it in Windows, every time the program
: : > emitted a 0x0A, Windows interpreted it as an lf, and
: : > preceded it with a spurious 0x0D cr. Cute. Is there
: : > some way I can freopen() (so to speak) stdout in binary
: : > mode under Windows so that doesn't happen? Hopefully,
: : > the fix would be portable, so it could compile and
: : > execute under Unix, too, with no ill effects. Thanks,

: : try _setmode()
: : Search _setmode (third hit) in
: : http://msdn.microsoft.com/library
: : --
: : Toni Uusitalo

: Thanks, Toni. As suggested, I modified code to include,
: essentially,
: if ( _setmode(_fileno(stdout), _O_BINARY)
: == -1 ) ; /* error */
: guarded by an ugly #ifdef to determine whether or not
: it's a Windows compilation.
: Mailed fix to user who replied that he hasn't had time
: to try it yet, but is "sure it will work" -- poor, naive soul!
: I'll post another short followup when outcome is known,

User reports fix works exactly as intended.
Thanks again,
--
John Forkosh ( mailto: j@f.com where j=john and f=forkosh )
Nov 14 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Paul Watson | last post: by
5 posts views Thread by gof | last post: by
4 posts views Thread by Rouben Rostamian | last post: by
5 posts views Thread by Charles F McDevitt | last post: by
40 posts views Thread by rayw | last post: by
4 posts views Thread by Barry | last post: by
24 posts views Thread by Bartc | last post: by
27 posts views Thread by CarlosMB | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
1 post views Thread by Geralt96 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.