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

发布于 2024-11-29 13:48:38 字数 993 浏览 2 评论 0原文

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

我做错了什么?

I'm trying to parse data from stdin in binary mode under Win32.
The first thing my code does is to check for a 4byte header at the beginning:

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 has been switched to binary mode before reading from it:

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);
}

This code works fine under Linux, however on Win32 (specifically Windows XP), the fread only seems to read a single byte and thus cause the evaluation to fail.
Example:

> 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

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拔了角的鹿 2024-12-06 13:48:38

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

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

According to the MSDN documentation, it's not permitted to pass NULL for the path parameter of freopen, so the call to freopen is almost certainly failing; have you checked the return value and the value of errno? C89 does not specify the behavior of freopen when path is NULL; C99 does, but the Microsoft C runtime is not (and does not claim to be) C99-compliant.

If you really need to read binary info from stdin, you might have to use platform-specific code and read the raw binary data directly with ReadFile on the file GetStdHandle(STD_INPUT_HANDLE).

甜`诱少女 2024-12-06 13:48:38

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

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

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

更新/摘要

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

At http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html I have found the following:

If filename is a null pointer, the freopen() function shall attempt to
change the mode of the stream to that specified by mode, as if the
name of the file currently associated with the stream had been used.
In this case, the file descriptor associated with the stream need not
be closed if the call to freopen() succeeds. It is
implementation-defined which changes of mode are permitted (if any),
and under what circumstances.

Maybe you should check if the change of mode (from text to binary) is allowed by the compiler and libraries you are using. Which compiler are you using?

Update / summary

Using MinGW you can call setmode() to switch the mode of the stdin stream.
You should set the mode to _O_BINARY, which is defined in fcntl.h.
For more information see e.g. http://gnuwin32.sourceforge.net/compile.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文