【问题标题】:Problems using fread() on stdin under win32win32下在标准输入上使用fread()的问题
【发布时间】:2011-10-26 13:02:57
【问题描述】:

我正在尝试在 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

我做错了什么?

【问题讨论】:

  • 如果您不执行 freopen 会发生什么?
  • 标头检查正常,但由于 windows 处理换行符的方式不同,我稍后运行的其他检查得到了无意义的结果:-/
  • 好的。我只是想仔细检查一下这个问题是否特定于重新打开的标准输入,而不仅仅是一般的 Windows。
  • 是否可以过滤输入并将\r\n序列转换为\n?

标签: c windows pipe stdio


【解决方案1】:

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

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

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

更新/总结

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

【讨论】:

  • 我在 MinGW 下使用 GCC 4.5.2。
【解决方案2】:

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

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

【讨论】:

  • setmode(fileno(stdin), O_BINARY); MSDN
  • @user786653:啊,好电话,我不知道这个功能。您应该将其添加为答案。
  • setmode() 也应该适用于 MinGW。请参阅gnuwin32.sourceforge.net/compile.html,“文本文件和二进制文件”部分。
  • @user786653:当我尝试这样做时,编译器抱怨它找不到 O_BINARY 的声明。我包括io.h,虽然:-/
  • MinGW下应该是#include ,常量是_O_BINARY(见上面的链接)。
猜你喜欢
  • 1970-01-01
  • 2011-01-23
  • 2017-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多