C чтение (из стандартного ввода) останавливается на 0x1a символ

В настоящее время я реализую преобразование Берроуза-Уилера (и обратное преобразование) для необработанных данных (например, JPG и т. д.). При тестировании на обычных данных, таких как текстовые файлы, никаких проблем не возникает. Но когда дело доходит до чтения файлов jpg, например, он прекращает чтение с символа 0x1a, также известного как символ замены Я искал в Интернете решения, которые не принимают зависимый от ОС код, но без результатов... Я думал читать в stdin в двоичном режиме, но это не так просто, я думаю. Есть ли простой способ решить эту проблему?

код:

buffer = (unsigned char*) calloc(block_size+1,sizeof(unsigned char));
length = fread((unsigned char*) buffer, 1, block_size, stdin);
if(length == 0){
    // file is empty
}else{
    b_length = length;
    while(length == b_length){
        buffer[block_size] = '\0';
        encodeBlock(buffer,length);
        length = fread((unsigned char*) buffer, 1, block_size, stdin);      
    }
    if(length != 0){            
        buffer[length] = '\0';
        encodeBlock(buffer,length);
    }
}
free(buffer);

5 ответов

Как вы заметили, вы читаете из stdin в режиме ASCII, и он ударяет по символу SUB (заменитель, он же CTRL + Z, он же DOS End-of-File).

Вы должны изменить режим на двоичный с setmode в то время как на Windows:

#if defined(WIN32)
#include <io.h>
#include <fcntl.h>
#endif /* defined(WIN32) */

/* ... */

#if defined(WIN32)
_setmode(_fileno(stdin), _O_BINARY);
#endif /* defined(WIN32) */

На платформах, отличных от Windows, вы не сталкиваетесь с этим различием в режимах.

Вы не можете сделать это без зависимости от ОС. Спецификация языка C гласит (7.19.3)

При запуске программы три текстовых потока предопределены...

stdin текстовый поток В зависимости от вашей ОС, могут быть способы изменить режим существующего потока или получить доступ к данным низкоуровневого потока, но вы утверждаете, что вам не нужен какой-либо специфичный для ОС код.

Ты можешь использовать _setmode конвертировать стандартный ввод в двоичный режим.

Существует также freopen - см этот вопрос так

Вы должны открыть файл как двоичный файл.

Используйте что-то похожее на

fopen("file", "rb");

Использование read() читать в данных.
Поскольку вы заинтересованы в получении данных от stdin использовать

fd = fcntl(STDIN_FILENO, F_DUPFD, 0);

чтобы получить fd из stdin,

Больше информации здесь.

Эта проблема связана с тем, что Windows рассматривает 0x1a иначе CTRL+Z как EOF, Как отметил Эрлз, открытие в двоичном режиме исправляет это в Windows и работает и в Linux.

Другие вопросы по тегам