简体   繁体   中英

C Read binary file to a buffer

I'm trying to create a simple VM that can read in a binary file, follow the instructions in the binary (4 words each instruction - 32 bit), and then output the result after following all instructions.

I'm currently in the first phase of my project , and am trying to use fread/fopen to read in the contents of my file into a buffer. For the most part the code is similar to the example given on fread for cplusplus.com, however I want to find a way to break my file into 4 words at a time. I've never worked at such a low level before, and am having problems finding out whether or not I am doing this correctly, and was hoping someone here could help me make sure I'm breaking the file up into 4 words correctly.

FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;

  pFile = fopen ( "test.bin" , "rb" );

  if (pFile==NULL) {fprint("error, file null")}

  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  rewind (pFile);

  // allocate memory to contain the whole file:
  buffer = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
  if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

  // copy the file into the buffer:
  result = fread (buffer, 4,lSize,pFile); //The error is here, if I use 1 instead of 4 there is no error output but I am not sure this would properly break the file into 4 words read at a time.
  if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
   printf("%ld\n",lSize);

Right now when I run this I am getting an error, unless I change the number in the line that I commented back to 1.

Representing a binary file as a buffer is something that your OS can do for you; the man page of mmap has a working example in C89 (so it's antique):

       fd = open(argv[1], O_RDONLY);

...

       if (fstat(fd, &sb) == -1)           /* To obtain file size */
           handle_error("fstat");

       offset = atoi(argv[2]);
       pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
           /* offset for mmap() must be page aligned */

...

       if (argc == 4) {
           length = atoi(argv[3]);
           if (offset + length > sb.st_size)
               length = sb.st_size - offset;
                   /* Can't display bytes past end of file */

       } else {    /* No length arg ==> display to end of file */
           length = sb.st_size - offset;
       }

       addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
                   MAP_PRIVATE, fd, pa_offset);
       if (addr == MAP_FAILED)
           handle_error("mmap");

Now, addr points to a memory region containing the input file in your process' address space.

This will save you reading the whole file before the start of processing, as your OS can automatically read only the parts of the file you're actually accessing without further ado.

Also, since you're writing a VM (whatever that means to you!) you should be aware of typical process memory structures, so learning what mmap does is an excellent excercise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM