我正在尝试在Win32下以二进制模式解析stdin中的数据。 我的代码所做的第一件事是在开头检查一个4字节的标题:
int riff_header;
fread(&riff_header, sizeof(riff_header), 1, ifp);
// 'RIFF' = little-endian
if (riff_header != 0x46464952) {
fprintf(stderr, "wav2msu: Incorrect header: Invalid format or endianness\n");
fprintf(stderr, " Value was: 0x%x\n", riff_header);
return -1;
}
在阅读之前, stdin
已切换到二进制模式:
if (*argv[argc-1] == '-') {
fprintf(stderr, "Reading from stdin.\n");
infile = stdin;
// We need to switch stdin to binary mode, or else we run
// into problems under Windows
freopen(NULL, "rb", stdin);
}
此代码在Linux下运行正常,但在Win32(特别是Windows XP)上,fread
似乎只读取单个字节,从而导致评估失败。
例如:
> ffmeg.exe -i ..\test.mp3 -f wav pipe:1 2> nul |..\foo.exe -o test.bin -
Reading from stdin.
foo: Incorrect header: Invalid format or endianness
Value was: 0x4
我做错了什么?
答案 0 :(得分:5)
在http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html我找到了以下内容:
如果filename是空指针,则freopen()函数应尝试 将流的模式更改为mode指定的模式,就好像是 已使用当前与流关联的文件的名称。 在这种情况下,与流关联的文件描述符不需要 如果对freopen()的调用成功,则关闭。它是 实现 - 定义允许的模式更改(如果有), 在什么情况下。
也许您应该检查您正在使用的编译器和库是否允许更改模式(从文本到二进制)。您使用的是哪种编译器?
更新/摘要
使用MinGW,您可以调用setmode()来切换stdin流的模式。 您应该将模式设置为_O_BINARY,它在fcntl.h中定义。 有关更多信息,请参阅http://gnuwin32.sourceforge.net/compile.html
答案 1 :(得分:5)
根据MSDN documentation,不允许NULL
传递path
的{{1}}参数,因此对freopen
的调用几乎肯定会失败;你检查了freopen
的返回值和值吗? errno
为freopen
时,C89未指定path
的行为; C99可以,但Microsoft C运行时不符合(并且声称不符合)C99。
如果您确实需要从NULL
读取二进制信息,则可能必须使用特定于平台的代码,并使用文件ReadFile
上的GetStdHandle(STD_INPUT_HANDLE)
直接读取原始二进制数据。< / p>