4

Normally I live in my guarded world of C#. But sometimes I have to break out and do something outside.

At the moment I have to decode an audiostream and have to output this directly in my c++ console application.

If I write the content into a file, I can hear the correct result. But if I use instead of a fstream cout, I get only a noisy sound.

How I have to do it correct? Here the working filestream code:

fstream wavefile;
wavefile.open(output, ios::out | ios::binary | ios::trunc);

//do something
wavefile.write((char*) &waveheader, waveheadersize);
//do something else
do {
        //do something
        //decodedBuffer is of type BYTE* , decodedLength is of type DWORD
        wavefile.write((char*) decodedBuffer, decodedLength);
        wavefile.flush();
    } while (encodedLength > 0);

My not working cout code:

std::cout.setf(ios::out | ios::binary | ios::trunc);

//do something
//this works, I got the same output
cout << structToString(&waveheader) << endl;
//do something else
do {
        //do something
        cout << (char *)decodedBuffer;
    } while (encodedLength > 0);

Thanks in advance

Mitja
  • 863
  • 5
  • 22
  • just redirect output when you use `std::cout` to a file and compare – Slava Oct 28 '14 at 19:07
  • 4
    None of `ios::out`, `ios::binary` and `ios::trunc` are formatting-flags. See http://en.cppreference.com/w/cpp/io/ios_base/setf – Deduplicator Oct 28 '14 at 19:09
  • 1
    You'll need to include the actual error message, to make this a valid question. _"Not working code"_ is too vague. – πάντα ῥεῖ Oct 28 '14 at 19:11
  • Let me guess, you are on windows, and thus textmode translation on your streams is killing your data. – Deduplicator Oct 28 '14 at 19:13
  • 1
    And even if they were, `cout << (char *)decodedBuffer` invokes the formatted output inserter. You know `std::cout` still has a `write` method, right? It behaves as an [**unformatted output function**](http://en.cppreference.com/w/cpp/concept/UnformattedOutputFunction), which is likely what you want (and in fact used in your `std::fstream` write operation using [`std::basic_ostream::write`](http://en.cppreference.com/w/cpp/io/basic_ostream/write)). – WhozCraig Oct 28 '14 at 19:14
  • When you use `cout << (char *)buffer;`, it treats the data as a zero-terminated string, which means it stops writing at the first zero-value byte. In a case like this where you could (and apparently do) have zero-value bytes in the middle of the buffer, that's not going to work. – Jerry Coffin Oct 28 '14 at 19:18
  • Relevant: http://stackoverflow.com/questions/5654067/how-to-make-cout-behave-as-in-binary-mode – Deduplicator Oct 28 '14 at 19:19
  • @WhozCraig: unfortunately you are wrong on Windows. line endings will be transformed to \r \n with cout. You need to set the mode to binary via `_setmode(_fileno(stdout), _O_BINARY);` – fmuecke Aug 07 '15 at 20:33

3 Answers3

5

First, there is absolutely no reason to use different code for a std::fstream and for std::cout (Beside which, your cout-code uses formatted output, and wrong):

You are using their ostream-interface in both cases.

So, first things first, repair the second code (as far as possible) by replacing it with the first.


Now, we come to the one difference (which you tried to paper over with setf): std::cout is in text-mode, not binary mode!

Unfortunately, none of ios::out, ios::binary and ios::trunc are formatting-flags, so you cannot set them with setf.

Actually, the mode cannot be changed at all after the fact (at least not portably).

Fortunately, you can simply ignore having the wrong mode on many systems, as Linux and others equate textmode and binary-mode. On windows, this hack should get you around it:

cout.flush();
fflush(stdout);
_setmode(_fileno(stdout), _O_BINARY);
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
1

The simple answer is that you can't. You need to output in binary mode. The mode is selected, once and for all, when you open the file, and std::cout is always opened in text mode.

Since you're just writing a block of bytes, the simplest solution is to use the system level requests. Under Windows, for example, you can use GetStdHandle( STD_OUTPUT_HANDLE ) to get the handle to standard out, and WriteFile to write a block of bytes to it. (Under Unix, the file descriptor for standard out is always 1, and the function is write. But since there is no difference between text mode and binary mode under Unix, I assume that this isn't your case.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Certainly also a worthwhile idea to just drop down to the raw OS-API, though I guess he wanted to stay with an `ostream`-interface. – Deduplicator Oct 29 '14 at 17:11
  • @Deduplicator It would be perhaps understandable for reasons of portability, but since there isn't a portable solution... – James Kanze Oct 29 '14 at 17:34
-2

Try this,

    std::cout.write(reinterpret_cast<char*>(decodedBuffer), decodedLength);

But I am not sure if structToString(&waveheader) work correctly, but you seem okay with it.

m. c.
  • 867
  • 5
  • 12
  • what he wants is to output a chuck of memory, starting from decodedBuffer, the length is decodedLength. Not string representation of the data. – m. c. Oct 28 '14 at 19:32
  • Yes. But `cout` is in text-mode, thus his data will still be garbled. – Deduplicator Oct 28 '14 at 19:34
  • At the end I used a mix of @Deduplicator and user3183610. So its not that bad. Thank you. – Mitja Oct 28 '14 at 20:05