C read binary stdin

Viewed 41226

I'm trying to build an instruction pipeline simulator and I'm having a lot of trouble getting started. What I need to do is read binary from stdin, and then store it in memory somehow while I manipulate the data. I need to read in chunks of exactly 32 bits one after the other.

How do I read in chunks of exactly 32 bits at a time? Secondly, how do I store it for manipulation later?

Here's what I've got so far, but examining the binary chunks I read further, it just doesn't look right, I don't think I'm reading exactly 32 bits like I need.

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

How do I read in 32 bits at a time (they are all 1/0, no newlines etc), and what do I store it in, is char[] okay?

EDIT: I'm able to read the binary in but none of the answers produce the bits in the correct order — they are all mangled up, I suspect endianness and problems reading and moving 8 bits around ( 1 char) at a time — this needs to work on Windows and C ... ?

8 Answers

I had to piece the answer together from the various comments from the kind people above, so here is a fully-working sample that works - only for Windows, but you can probably translate the windows-specific stuff to your platform.

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
#include <io.h>
#include <fcntl.h>

int main()
{
    char rbuf[4096];
    char *deffile = "c:\\temp\\outvideo.bin";
    size_t r;
    char *outfilename = deffile;
    FILE *newin;

    freopen(NULL, "rb", stdin);
    _setmode(_fileno(stdin), _O_BINARY);

    FILE *f = fopen(outfilename, "w+b");
    if (f == NULL)
    {
        printf("unable to open %s\n", outfilename);
        exit(1);
    }

    for (;; )
    {
        r = fread(rbuf, 1, sizeof(rbuf), stdin);
        if (r > 0)
        {
            size_t w;
            for (size_t nleft = r; nleft > 0; )
            {
                w = fwrite(rbuf, 1, nleft, f);
                if (w == 0)
                {
                    printf("error: unable to write %d bytes to %s\n", nleft, outfilename);
                    exit(1);
                }
                nleft -= w;
                fflush(f);
            }
        }
        else
        {
            Sleep(10); // wait for more input, but not in a tight loop
        }
    }

    return 0;
}

For Windows, this Microsoft _setmode example specifically shows how to change stdin to binary mode:

// crt_setmode.c
// This program uses _setmode to change
// stdin from text mode to binary mode.

#include <stdio.h>
#include <fcntl.h>
#include <io.h>

int main( void )
{
   int result;

   // Set "stdin" to have binary mode:
   result = _setmode( _fileno( stdin ), _O_BINARY );
   if( result == -1 )
      perror( "Cannot set mode" );
   else
      printf( "'stdin' successfully changed to binary mode\n" );
}
Related