Подтвердить что ты не робот

C читать двоичный stdin

Я пытаюсь создать симулятор конвейера команд, и у меня возникли проблемы с запуском. То, что мне нужно сделать, это прочитать двоичный файл из stdin, а затем сохранить его в памяти, пока я манипулирую данными. Мне нужно читать куски ровно 32 бита один за другим.

Как читать в кусках ровно 32 бита за раз? Во-вторых, как сохранить его для манипуляции позже?

Вот то, что у меня есть до сих пор, но изучая бинарные куски, которые я читаю дальше, это просто не выглядит правильным, я не думаю, что читаю ровно 32 бита, как мне нужно.

char buffer[4] = { 0 }; // initialize to 0
unsigned long c = 0;
int bytesize = 4; // read in 32 bits
while (fgets(buffer, bytesize, stdin)) {
  memcpy(&c, buffer, bytesize); // copy the data to a more usable structure for bit manipulation later
  // more stuff
  buffer[0] = 0; buffer[1] = 0; buffer[2] = 0; buffer[3] = 0; // set to zero before next loop
}
fclose(stdin);

Как я могу читать по 32 бита за раз (все они 1/0, нет строк и т.д.), и что я храню в нем, char[] okay?

EDIT: я могу прочитать двоичный файл, но ни один из ответов не порождает биты в правильном порядке - все они искалечены, я подозреваю, что суждение и проблемы с чтением и перемещением 8 бит вокруг (1 char) в то время - это нужно для работы с Windows и C...?

4b9b3361

Ответ 1

У меня это было в первый раз, за ​​исключением того, что мне было нужно ntohl... C Endian Conversion: по-бит

Ответ 2

Вам нужно freopen(). С manpage:

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

В принципе, лучшее, что вы действительно можете сделать, это следующее:

freopen(NULL, "rb", stdin);

Это приведет к повторному открытию stdin того же входного потока, но в двоичном режиме. В обычном режиме чтение из stdin в Windows преобразует \r\n (Windows newline) в один символ ASCII 10. Использование режима "rb" отключает это преобразование, чтобы вы могли правильно читать в двоичных данных.

freopen() возвращает дескриптор файла, но это предыдущее значение (прежде чем мы поместим его в двоичном режиме), поэтому не используйте его ни для чего. После этого используйте fread(), как было упомянуто.

Что касается ваших проблем, вы можете не читать "32 бита", но если вы используете fread(), вы будете читать в 4 char (это лучшее, что вы можете сделать в C - char гарантируется как минимум 8 бит, но некоторые исторические и встроенные платформы имеют 16 бит char (некоторые даже имеют 18 или хуже)). Если вы используете fgets(), вы никогда не будете читать в 4 байта. Вы будете читать как минимум 3 (в зависимости от того, является ли какая-либо из них символами новой строки), а 4-й байт будет '\0', потому что строки C имеют nul-terminated и fgets() nul-завершает то, что он читает (например, хорошая функция), Очевидно, это не то, что вы хотите, поэтому вы должны использовать fread().

Ответ 4

fgets() здесь не так. Он нацелен на текст, читаемый человеком, ASCII, который заканчивается символами конца строки, а не двоичными данными, и не получит вас, что вам нужно.

Недавно я сделал именно то, что вы хотите, используя вызов read(). Если ваша программа явно закрыла stdin, для первого аргумента (дескриптор файла) вы можете использовать постоянное значение 0 для stdin. Или, если вы находитесь в системе POSIX (Linux, Mac OS X или какой-либо другой современный вариант Unix), вы можете использовать STDIN_FILENO.

Ответ 5

Я не знаю, какую ОС вы используете, но вы обычно не можете "открывать stdin в двоичном формате". Вы можете попробовать что-то вроде

int fd = fdreopen (fileno (stdin), outfname, O_RDONLY | OPEN_O_BINARY);

чтобы попытаться заставить его. Затем используйте

uint32_t opcode;
read(fd, &opcode, sizeof (opcode));

Но я сам этого не пробовал.:)

Ответ 6

fread() лучше всего подходит для чтения двоичных данных.

Да, массив char в порядке, если вы планируете их обрабатывать по очереди.