[comp.lang.c++] Changing cout mode to ios::binary in Borland C++

UH2@psuvm.psu.edu (Lee Sailer) (05/03/91)

The sybject line says most of i, I guess.  MSDOS has that ittitating
habit of adding a CR whenever it outputs a NL, which is fine until
you try to write a program that writes a "binary" file to cout.

I've tried the obvious things, without luck.  For example

cout << setiosflags(ios::binary) << "\n";

still sends a crlf pair to the stdout.  I called Borland tech support,
but they didn't seem to understand why one might ever wish to
do what I want to do.

So--in short.  Can I turn off the \n --> \r\n translation for cout?

lee

Lee Sailer <UH2@psuvm.psu.edu> (05/06/91)

For those of you who might be interested, it looks like this might be
"impossible."  I got several suggestions for the obvious workarounds, but
I need the real solution in this case.  Oh well.  One response was
especially interesting, and seemed like it might be of general enough
interest that I've decided to post it here.  I've edited it to
preserve the authors anonymity.  If he wanted it posted under his
name, I guess he'd have done so.

So, an anonymous author says....


I can't speak for the Borland library, but I think I can probably shed
a little light on the subject for you.

In general, once a stream/file is open with some mode, the only
way to change its mode is to close it and reopen it.  I know that
at times this is a pain, but if you think about it, it is a necessary
restriction.  You see, there is a fair amount of machinery necessary
to properly take care of (the idiotic) CR/LF translation for DOS.
Low-level IO is probably the single largest source of bug reports
in our library, and among those, CR/LF translation is a favorite.
I spend an inordinate amount of time working on this code.  It
seems simple, but there are a huge number of problems associated
with it.  In addition, there may be systems on which the difference
between text and binary files is more than just newline translation.
For example, a system may require that all characters in a text
file have the high bit clear.  I can't think of such a system off
hand, but it is possible and the ANSI C standard takes this into
account.

Anyway, once the machinery is set in motion, it may not be possible
to change a file from text to binary mode without completely resetting
the file.  Rather than having the library do it "under the covers",
the user is forced to do it by closing and reopening the file.  This
avoids unexpected surprises.

I have considered this problem in relation to the C++ streams package,
which supposedly makes it simple to modify the characteristics of
a stream on the fly.  My decision is that it is just too complex a
problem to allow the text/binary mode to change after a file has
been opened.  I suspect that this is also the decision made by
Borland.

Granted, CR/LF translation is especially simple for output streams, but
it is necessary to restrict the ability to change modes in order to
keep the functionality of the library consistent.  Otherwise people
would be asking "Why can't I change cin to binary, it works for
cout?".  We are consistent in that you are not allowed to change
the mode of a file, nor are you allowed to change the buffering
status or the buffer size after the file has been used.  Once
the file has been used, the user can make no assumptions about
the state of the buffer, therefore the user cannot expect to
modify the buffering status.  In the case of C++, the file mode
is only interrogated when the file is opened, so modifying it
later would have no effect.

If you really need to make cout be a binary stream, I would suggest
that you use the filebuf members (attach, etc.) to create a filebuf
that suites your needs, then attach cout to that filebuf.   Now that I
look at the header files, this presents another problem -- there is no
way to specify the mode of a file except in filebuf::open().  Since you
want to use a descriptor set up by the runtime initializer, you can't
use open().  So, you could use the filebuf constructor that takes a
single 'int' argument and see what effective mode Borland gives you
when you attach to handle 1.  I think our library will by default give
you a text stream unless you ask for a binary stream, so it wouldn't
work under [author's] library.  If this fails under Borland as well,
you are left with two choices:  1) use a file instead of cout, or 2)
get the source to Borland's runtime initializer and modify it to open
handle 1 as binary.

Sorry, I guess this pretty much turned out to be bad news.
I will make a note of this problem so I can address it in
our library, and I may pass it on to the ANSI committee
if I can come up with a decent solution.

sking@nowhere.uucp (Steven King) (05/08/91)

In article <91126.163800UH2@psuvm.psu.edu> UH2@psuvm.psu.edu (Lee Sailer) writes:
>For those of you who might be interested, it looks like this might be
>"impossible."  I got several suggestions for the obvious workarounds, but
>I need the real solution in this case.  Oh well.  One response was
>especially interesting, and seemed like it might be of general enough
>interest that I've decided to post it here.  I've edited it to
>preserve the authors anonymity.  If he wanted it posted under his
>name, I guess he'd have done so.
>
>So, an anonymous author says....
>

   [ anon message why it might not be good to do this ]

   I dont know about borland, but microsoft c provides a "setmode" function
 in their C lib to do this, and it works on stdout. ie.:


#include <iostream.h>

extern "C" int setmode ( int, int ) ;
#define  O_BINARY 0x8000 

main ( )
{
   cout << "foo\n" << flush ;
   setmode ( 1, O_BINARY ) ;
   cout << "foo bar\n" << flush ;
}


   I would be very surprised if borland didnt provide something with the same
 functionality...


-- 
If it don't stick, stink, or sting
It ain't from Texas.
                                        ..!cs.utexas.edu!ut-emx!nowhere!sking

davidc@vlsisj.uucp (David Chapman) (05/09/91)

In article <91126.163800UH2@psuvm.psu.edu>, UH2@psuvm.psu.edu (Lee
Sailer) writes:
|> So, an anonymous author says....
|> 
|> with it.  In addition, there may be systems on which the difference
|> between text and binary files is more than just newline translation.

Under VMS (a DEC operating system, in case you didn't know :-), text
files are normally stored in VAR (variable length record) format.  Every
line has a length at the front of it.  There really aren't any "newline"
characters in the file and it's not possible to perform random accesses
in this type of file (not that we've been able to figure out).  Binary
files are stored in fixed-length records, which you can seek in.

|> Anyway, once the machinery is set in motion, it may not be possible
|> to change a file from text to binary mode without completely resetting
|> the file.

Or rewriting the file completely.  :-(

                David Chapman

{known world}!decwrl!vlsisj!davidc
vlsisj!davidc@decwrl.dec.com