如何最简单地从 std::cin
读取二进制(非格式化)数据并将其存储到 string
或 stringstream
中?
std::cin
没有使用ios_binary打开。如果必须使用cin,则需要重新打开它,这不是标准的一部分。
一旦它是二进制的,你可以使用cin.read()
来读取字节。如果你知道在你的系统中,文本和二进制没有区别(并且你不需要可移植性),则可以放心地使用read。
对于Windows操作系统,你可以使用与已经提到了的cin.read()
函数结合使用的_setmode
函数。
_setmode(_fileno(stdin), _O_BINARY);
cin.read(...);
查看解决方案源代码:http://talmai-oliveira.blogspot.com/2011/06/reading-binary-files-from-cin.html
_setmode(_fileno(stdin), _O_BINARY);
和 vector<char> v(static_cast<size_t>(len), 0); cin.read(&v[0], len);
。
你需要包含 fcntl.h
和 io.h
来实现这个功能。 - fmuecke所有预定义的 iostream 对象都必须绑定到相应的 C 流:
对象
cin
控制着与对象stdin
关联的流缓冲区的输入,声明在<cstdio>
中。
http://eel.is/c++draft/narrow.stream.objects
因此,获取二进制数据的方法与 C 相同:
基本上,你真正能做的最好的事情是这样:
freopen(NULL, "rb", stdin);
这将重新打开标准输入,但采用二进制模式。在普通模式下,在 Windows 上从 stdin 读取将把
\r\n
(Windows 换行符)转换为单个字符 ASCII 10。使用“rb”模式禁用此转换,以便您可以正确地读取二进制数据。
cin.get()
方法逐字节读取并将数据保存到容器中,例如std::vector<unsigned int>
,或者您可以使用cin.read()
来读取固定数量的字节到缓冲区中。还可以使用cin.peek()
检查是否有任何数据流结束指示符。operator>>
重载...使用operator>>
会导致在观察到分隔符字符时发生中断,并且它还将从流本身中删除分隔符字符。这将包括任何等效于空格、制表符等的二进制值。因此,使用该方法从std::cin
存储的二进制数据将无法逐字节匹配输入二进制流。cin
仍处于文本模式。这对于类Unix系统可能不重要,但在Windows上,例如,每个 CR LF
行尾将仍被转换为单个 '\n'
字符。 - Keith Thompsoncin.read
会存储一定数量的字节,没有逻辑搜索@Jason提到的分隔符类型。
但是,仍然可能存在在流上活动的转换,例如CRLF -> NL,因此对于二进制数据仍不理想。
在Windows/Mingw/MSYS/Bash中,如果您需要在不同的命令之间使用二进制流进行管道传输,则需要将std :: cin和std :: cout作为二进制流进行操作。
Mikhail提供的_setmode解决方案非常完美。
使用MinGW,所需的头文件如下:
#include <io.h>
#include <fcntl.h>
std::freopen
的讨论(但它看起来有点hacky)。如果有人能提供Linux、OS X、Solaris和Windows的示例,那就太好了。 - jww