What is the easiest way to read binary (non-formated) data from std::cin
into either a string
or a stringstream
?
-
Why not open an ifstream with "/dev/stdin" in binary mode? – Sep 28 '11 at 18:18
-
2@WTP Wouldn't work on anything that isn't Unix. – Jonathan Sternberg Sep 28 '11 at 18:26
-
1Also see the discussion of using [`std::freopen`](https://stackoverflow.com/a/39758021/608639) (but it looks kind of hacky). It would be nice if someone provided a canonical answer with examples for Linux, OS X, Solaris and Windows. – jww May 20 '18 at 18:26
7 Answers
std::cin
is not opened with ios_binary. If you must use cin, then you need to reopen it, which isn't part of the standard.
Some ideas here: https://comp.unix.programmer.narkive.com/jeVj1j3I/how-can-i-reopen-std-cin-and-std-cout-in-binary-mode
Once it's binary, you can use cin.read()
to read bytes. If you know that in your system, there is no difference between text and binary (and you don't need to be portable), then you can just use read without worrying.

- 87,846
- 14
- 132
- 192
For windows, you can use the _setmode
function in conjunction with cin.read()
, as already mentioned.
_setmode(_fileno(stdin), _O_BINARY);
cin.read(...);
See solution source here: http://talmai-oliveira.blogspot.com/2011/06/reading-binary-files-from-cin.html

- 20,685
- 7
- 70
- 146
-
1Finally working for Windows! `_setmode(_fileno(stdin), _O_BINARY);` and `vector
v(static_cast – fmuecke Aug 07 '15 at 19:32(len), 0); cin.read(&v[0], len);` You need to include `fcntl.h` and `io.h` to do this.
All predefined iostream objects are obligated to be bound to corresponding C streams:
The object
cin
controls input from a stream buffer associated with the objectstdin
, declared in<cstdio>
.
http://eel.is/c++draft/narrow.stream.objects
and thus the method of obtaining binary data is same as for C:
Basically, the best you can really do is this:
freopen(NULL, "rb", stdin);
This will reopen stdin to be the same input stream, but in binary mode. In the normal mode, reading from stdin on Windows will convert
\r\n
(Windows newline) to the single character ASCII 10. Using the "rb" mode disables this conversion so that you can properly read in binary data.

- 5,190
- 2
- 32
- 59

- 332
- 2
- 17
On a Unix/POSIX system, you can use the cin.get()
method to read byte-by-byte and save the data into a container like a std::vector<unsigned int>
, or you can use cin.read()
in order to read a fixed amount of bytes into a buffer. You could also use cin.peek()
to check for any end-of-data-stream indicators.
Keep in mind to avoid using the operator>>
overload for this type of operation ... using operator>>
will cause breaks to occur whenever a delimiter character is observed, and it will also remove the delimiting character from the stream itself. This would include any binary values that are equivalent to a space, tab, etc. Thus the binary data your end up storing from std::cin
using that method will not match the input binary stream byte-for-byte.

- 31,834
- 7
- 59
- 78
-
4`cin` is still in text mode. That probably won't matter for Unix-like systems, but on Windows, for example, each `CR LF` line ending will still be translated to a single `'\n'` character. – Keith Thompson Sep 28 '11 at 19:43
cin.read
would store a fixed number of bytes, without any logic searching for delimiters of the type that @Jason mentioned.
However, there may still be translations active on the stream, such as CRLF -> NL, so it still isn't ideal for binary data.

- 277,958
- 43
- 419
- 720
With windows/mingw/msys/bash, if you need to pipe different commands with binary streams in between, you need to manipulate std::cin and std::cout as binary streams.
The _setmode solution from Mikhail works perfectly.
Using MinGW, the neaded headers are the following:
#include <io.h>
#include <fcntl.h>

- 123
- 10
Unformatted input
Most of the other member functions of the istream class are used to perform unformatted input, i.e. no interpretation is made on the characters got form the input. These member functions can get a determined number of characters from the input character sequence (get, getline, peek, read, readsome)...
As Lou Franco pointed out, std::cin isn't opened with std::ios_base::binary, but one of those functions might get you close to the behavior you're looking for.

- 36,103
- 8
- 58
- 81
-
2`might get you close to`: it might also get you in trouble, because the OS/library is entitled to do line-end conversions that potentially corrupt your binary data. It is _not_ clear to me that you read from 'read'/'readsome' or even directly from *rdbuf() (the stream buffer) is not already transformed in this way – sehe Sep 28 '11 at 19:04