在win32下的stdin上使用fread()的问题

我想parsing从二进制模式下的标准input数据在Win32下。 我的代码所做的第一件事是在开头检查一个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 

我究竟做错了什么?

Solutions Collecting From Web of "在win32下的stdin上使用fread()的问题"

http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html我发现了以下内容:

如果filename是一个空指针,freopen()函数将试图将流的模式改变为由mode指定的模式,就好像当前与流相关联的文件的名称已被使用。 在这种情况下,如果对freopen()的调用成功,则与该流关联的文件描述符不需要关闭。 它是实现定义模式的变化是允许的(如果有的话),以及在什么情况下。

也许你应该检查模式的改变(从文本到二进制)是否被编译器和你正在使用的库所允许。 你正在使用哪个编译器?

更新/摘要

使用MinGW你可以调用setmode()来切换标准输入流的模式。 您应该将模式设置为_O_BINARY,这在fcntl.h中定义。 有关更多信息,请参阅http://gnuwin32.sourceforge.net/compile.html

根据MSDN文档 ,不允许为freopenpath参数传递NULL ,所以调用freopen几乎肯定会失败; 你有没有检查返回值和errno的值? 当pathNULL时,C89不指定freopen的行为; C99的确如此,但是Microsoft C运行时并没有(也没有声称)符合C99标准。

如果您确实需要从stdin读取二进制信息,则可能需要使用特定于平台的代码,并直接使用文件GetStdHandle(STD_INPUT_HANDLE)上的ReadFile读取原始二进制数据。