Проблемы с использованием 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 3

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).