Проблемы с использованием fread () на stdin под win32 - PullRequest
3 голосов
/ 13 августа 2011

Я пытаюсь проанализировать данные со стандартного ввода в двоичном режиме под 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

Что я делаю не так?

Ответы [ 2 ]

5 голосов
/ 14 августа 2011

Согласно документации MSDN , не разрешено передавать NULL для параметра path freopen, поэтому вызов freopen почти наверняка завершится неудачей; Вы проверили возвращаемое значение и значение errno? C89 не определяет поведение freopen, когда path равно NULL; C99 делает, но среда выполнения Microsoft C не (и не претендует на то, что) C99-совместимым.

Если вам действительно нужно прочитать двоичную информацию из stdin, возможно, вам придется использовать специфичный для платформы код и читать необработанные двоичные данные напрямую с помощью ReadFile в файле GetStdHandle(STD_INPUT_HANDLE).

5 голосов
/ 14 августа 2011

В http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html Я нашел следующее:

Если filename является нулевым указателем, функция freopen () должна попытаться изменить режим потока на режим, указанный в mode, как если бы имя файла, связанного в данный момент с потоком. В этом случае файловый дескриптор, связанный с потоком, не должен быть закрытым, если вызов freopen () успешен. это определяется реализацией, какие изменения режима разрешены (если есть), и при каких обстоятельствах.

Возможно, вам следует проверить, разрешено ли изменение режима (с текстового на двоичный) компилятором и используемыми вами библиотеками. Какой компилятор вы используете?

Обновление / сводка

Используя MinGW, вы можете вызвать setmode () для переключения режима потока stdin. Вам следует установить режим _O_BINARY, который определен в fcntl.h. Для получения дополнительной информации, например, см. http://gnuwin32.sourceforge.net/compile.html

...