Проблемы с использованием fread() на stdin под win32
Я пытаюсь проанализировать данные из stdin в двоичном режиме под Win32. Первое, что делает мой код, - это проверяет наличие заголовка 4byte в начале:
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 endiannessn");
fprintf(stderr, " Value was: 0x%xn", 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
Что я делаю не так?
2 ответа:
В http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html я нашел следующее:
Если filename является нулевым указателем, функция freopen() попытается измените режим потока на тот, который указан в mode, как если бы было использовано имя файла, связанного в данный момент с потоком. В этом случае файловый дескриптор, связанный с потоком, не требуется будет закрыт, если вызов freopen () завершится успешно. Это реализация-определена какие изменения режима разрешены (если таковые имеются), и при каких обстоятельствах.
Возможно, вам следует проверить, разрешено ли изменение режима (от текстового до двоичного) компилятором и библиотеками, которые вы используете. Какой компилятор вы используете?
Обновление / сводка
Используя MinGW, вы можете вызвать setmode () для переключения режима потока stdin. Вы должны установить режим _O_BINARY, который определен в fcntl.х. Для получения дополнительной информации см., например, http://gnuwin32.sourceforge.net/compile.html
Согласно документации MSDN , не разрешается передавать
NULL
для параметраpath
freopen
, поэтому вызовfreopen
почти наверняка не выполняется; вы проверили возвращаемое значение и значениеerrno
? C89 не определяет поведениеfreopen
, Когдаpath
являетсяNULL
; C99 делает это, но среда выполнения Microsoft C не является (и не претендует на то, чтобы быть) C99-совместимой.Если вам действительно нужно прочитать двоичную информацию из
stdin
, вам, возможно, придется использовать специфичный для платформы код и считывание необработанных двоичных данных непосредственно с помощьюReadFile
на досьеGetStdHandle(STD_INPUT_HANDLE)
.