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.