Read and write to binary files in C? Read and write to binary files in C? c c

Read and write to binary files in C?


Reading and writing binary files is pretty much the same as any other file, the only difference is how you open it:

unsigned char buffer[10];FILE *ptr;ptr = fopen("test.bin","rb");  // r for read, b for binaryfread(buffer,sizeof(buffer),1,ptr); // read 10 bytes to our buffer

You said you can read it, but it's not outputting correctly... keep in mind that when you "output" this data, you're not reading ASCII, so it's not like printing a string to the screen:

for(int i = 0; i<10; i++)    printf("%u ", buffer[i]); // prints a series of bytes

Writing to a file is pretty much the same, with the exception that you're using fwrite() instead of fread():

FILE *write_ptr;write_ptr = fopen("test.bin","wb");  // w for write, b for binaryfwrite(buffer,sizeof(buffer),1,write_ptr); // write 10 bytes from our buffer

Since we're talking Linux.. there's an easy way to do a sanity check. Install hexdump on your system (if it's not already on there) and dump your file:

mike@mike-VirtualBox:~/C$ hexdump test.bin0000000 457f 464c 0102 0001 0000 0000 0000 00000000010 0001 003e 0001 0000 0000 0000 0000 0000...

Now compare that to your output:

mike@mike-VirtualBox:~/C$ ./a.out 127 69 76 70 2 1 1 0 0 0

hmm, maybe change the printf to a %x to make this a little clearer:

mike@mike-VirtualBox:~/C$ ./a.out 7F 45 4C 46 2 1 1 0 0 0

Hey, look! The data matches up now*. Awesome, we must be reading the binary file correctly!

*Note the bytes are just swapped on the output but that data is correct, you can adjust for this sort of thing


There are a few ways to do it. If I want to read and write binary I usually use open(), read(), write(), close(). Which are completely different than doing a byte at a time. You work with integer file descriptors instead of FILE * variables. fileno will get an integer descriptor from a FILE * BTW. You read a buffer full of data, say 32k bytes at once. The buffer is really an array which you can read from really fast because it's in memory. And reading and writing many bytes at once is faster than one at a time. It's called a blockread in Pascal I think, but read() is the C equivalent.

I looked but I don't have any examples handy. OK, these aren't ideal because they also are doing stuff with JPEG images. Here's a read, you probably only care about the part from open() to close(). fbuf is the array to read into,sb.st_size is the file size in bytes from a stat() call.

    fd = open(MASKFNAME,O_RDONLY);    if (fd != -1) {      read(fd,fbuf,sb.st_size);      close(fd);      splitmask(fbuf,(uint32_t)sb.st_size); // look at lines, etc      have_mask = 1;    }

Here's a write: (here pix is the byte array, jwidth and jheight are the JPEG width and height so for RGB color we write height * width * 3 color bytes). It's the # of bytes to write.

void simpdump(uint8_t *pix, char *nm) { // makes a raw aka .data file  int sdfd;  sdfd = open(nm,O_WRONLY | O_CREAT);  if (sdfd == -1) {    printf("bad open\n");    exit(-1);  }  printf("width: %i height: %i\n",jwidth,jheight);  // to the console  write(sdfd,pix,(jwidth*jheight*3));  close(sdfd);}

Look at man 2 open, also read, write, close. Also this old-style jpeg example.c: https://github.com/LuaDist/libjpeg/blob/master/example.c I'm reading and writing an entire image at once here. But they're binary reads and writes of bytes, just a lot at once.

"But when I try to read from a file it is not outputting correctly." Hmmm. If you read a number 65 that's (decimal) ASCII for an A. Maybe you should look at man ascii too. If you want a 1 that's ASCII 0x31. A char variable is a tiny 8-bit integer really, if you do a printf as a %i you get the ASCII value, if you do a %c you get the character. Do %x for hexadecimal. All from the same number between 0 and 255.


I'm quite happy with my "make a weak pin storage program" solution. Maybe it will help people who need a very simple binary file IO example to follow.

$ lsWeakPin  my_pin_code.pin  weak_pin.c$ ./WeakPinPin: 45 47 49 32$ ./WeakPin 8 2$ Need 4 ints to write a new pin!$./WeakPin 8 2 99 49Pin saved.$ ./WeakPinPin: 8 2 99 49$$ cat weak_pin.c// a program to save and read 4-digit pin codes in binary format#include <stdio.h>#include <stdlib.h>#define PIN_FILE "my_pin_code.pin"typedef struct { unsigned short a, b, c, d; } PinCode;int main(int argc, const char** argv){    if (argc > 1)  // create pin    {        if (argc != 5)        {            printf("Need 4 ints to write a new pin!\n");            return -1;        }        unsigned short _a = atoi(argv[1]);        unsigned short _b = atoi(argv[2]);        unsigned short _c = atoi(argv[3]);        unsigned short _d = atoi(argv[4]);        PinCode pc;        pc.a = _a; pc.b = _b; pc.c = _c; pc.d = _d;        FILE *f = fopen(PIN_FILE, "wb");  // create and/or overwrite        if (!f)        {            printf("Error in creating file. Aborting.\n");            return -2;        }        // write one PinCode object pc to the file *f        fwrite(&pc, sizeof(PinCode), 1, f);          fclose(f);        printf("Pin saved.\n");        return 0;    }    // else read existing pin    FILE *f = fopen(PIN_FILE, "rb");    if (!f)    {        printf("Error in reading file. Abort.\n");        return -3;    }    PinCode pc;    fread(&pc, sizeof(PinCode), 1, f);    fclose(f);    printf("Pin: ");    printf("%hu ", pc.a);    printf("%hu ", pc.b);    printf("%hu ", pc.c);    printf("%hu\n", pc.d);    return 0;}$