Workshop: Saving and Restoring Structures in Binary Files

UPI Study › Courses › Programming in C › Free lessons › Lesson 10.1 Free with a free account

Workshop: Saving and Restoring Structures in Binary Files

Programming in C · Chapter 10: Structures, Unions, and Compound Data ModelingSection 10.1 · lesson 64 of 787 min · free with a free account

← Workshop: A Text File Processing PipelineNext lesson: Defining Structures in C →

Earn 3 college credits for Programming in CRecommended for credit by NCCRS · Computer Science 240 · self-paced · one payment, lifetime access

In this lesson

Serializing struct records to binary files with fwrite and fread.

  • Explain serializing and why data in memory must be saved to a file
  • Save and restore a struct or an array of structs with one fwrite and one fread
  • Zero a struct before saving it and check the counts fwrite and fread return
  • Explain how padding, byte order, and layout changes tie a struct file to its program

Free study notes

Get this lesson's notes by email

The key points and 4 practice questions with answers, in your inbox. One email, free.

One email. Unsubscribe in one click.

Transcript

Everything said in the video, section by section (1,033 words). Read along, or search it.

The Problem

Scores Vanish When the Program Ends

The Starlight Arcade closes at midnight, and the lights go off. In the morning, the high-score board must still show last night's heroes. But a variable lives only while its program runs. When the program ends, every score in memory is gone. So the scores must go into a file before the program ends, and come back the next time it starts. Turning data in memory into bytes you can store is called serializing. Today you'll do it with a whole player record at once.

Quick Primer

Just Enough Struct to Start

First, just enough struct. Structures get their full lesson in 10.2. This workshop needs only a tiny piece. A struct is your own bundle type: several variables, called members, stored together under one name. struct Player bundles a name of 16 characters, room for 15 letters and the end mark, with an int score. hero is one variable of that type. Writing hero dot score reaches the score inside it. Build and run: Mira, 4200. And the whole struct takes 20 bytes: 16 for the name, then 4 for the score, in one block. Because it's one block, a single fwrite can copy the whole player to a file in one go.

Step One

Saving a Player at Closing Time

Here's Priya's save program, the one that runs at closing time. It starts hero at all zeros, then fills in the name and the score. Why zeros first? The name box has 16 places, and Mira uses five, counting the end mark. Without the zeros, leftovers from memory would be saved too. Open hero.bin with w b: write, in binary. If fopen fails, it returns NULL, and the program stops. Then one fwrite: the address of hero, the size of hero, a count of one item, and the file. fwrite returns how many items it wrote. Build and run: saved one player. Then the program ends, and hero is gone.

Inside the File

Reading the Saved Bytes in Hex

The program has ended, but the file is still there. Ask how big it is: 20 bytes, exactly one struct Player. Now look inside with xxd, a tool that prints a file's bytes in hex. These options show four bytes a row. The first row is 4d 69 72 61: M, i, r, a. Then come zeros: the end mark, and the unused places of the name. The last row, from byte 16, is the score. 68 10 means hex 1068, which is 4200, stored low byte first, as in 9.9.

Step Two

Loading the Player Next Morning

Next morning, a different program starts: Priya's loader. Its variable, loaded, begins as all zeros. It uses the very same struct Player blueprint, so the bytes land in the same members. Open the file with r b: read, in binary. If there's no save file yet, say so and stop. Then one fread: where to put the bytes, the size of one item, how many items, and which file. It returns how many items it really read. Build and run. fread returned 1, and Mira is back with her 4200 points. Last night's score survived the restart.

Arrays of Records

Saving Three Players in One Call

A board has more than one hero. Keep the players in an array of structs: records back to back, in one block. Lesson 10.3 covers it fully. Because the block is one piece, one fwrite with a count of 3 saves all three players, and one fread loads them into a second array, back. To keep the demo short, this program skips the NULL checks. Real programs keep them. Then the proof. For each restored player, strcmp compares the name, and double equals compares the score. The loop runs to got, the number really read, not a typed 3. So a short file can never make it visit empty boxes. Build and run. Wrote 3, read 3, and every player matches. The file holds 60 bytes. Player number k starts at byte 20 times k, so fseek, from 9.8, could jump straight to any player.

Hidden Bytes

Padding Between a Char and an Int

Our struct Player was lucky: 16 plus 4 is exactly 20. Often the compiler adds invisible gaps, called padding. Here's a struct with a char, then an int. The members add up to 5 bytes. offsetof, from stddef.h, says where a member starts. Run it on this Mac. The struct takes 8 bytes, and n starts at byte 4. Three unused bytes sit after tag, so that the int starts at a multiple of 4, a spot the processor likes. The compiler chooses the gap. Another compiler, or another kind of machine, may choose differently.

Quick Check

A New Member Breaks the Old Loader

Quick check. Priya adds a tokens member to the save program, between name and score, and gives hero 12 tokens. She rebuilds the save program and runs it. The loader stays exactly as it was. What does the loader print now? Pause and predict. Build the new saver, run it, then run the old loader: Mira with 12 points. fread still returned 1. The file now holds 24 bytes, and tokens sits at bytes 16 to 19. The loader reads 20 bytes into its old blueprint, so it takes those 4 bytes as the score. The real 4200 is never read. And fread can't warn you: it read one item of 20 bytes, exactly as asked. A file of raw structs has no labels.

Limits

Why Struct Files Rarely Travel

That's the catch with struct files. The bytes depend on the program, the compiler and the machine. The size of an int, the byte order, and the padding can all differ. So can the members, as you just saw. A struct file works well when the same program, built the same way, reads it back, as in the arcade. To share data between different systems, write text with fprintf, from 9.7, or save each member in a format you define.

Key Takeaways

One Block Out, One Block Back

To sum up. A struct is one block, so one fwrite saves a whole record, and one fread restores it. Start with all zeros, and check every count the functions return. An array of structs saves and loads in a single call. And padding, byte order and layout tie the file to the program that wrote it.

Try It

Counting Records Without a Stored Count

Something to try. Without a stored count, how could a loader find out how many players team.bin holds? Hint: fseek to the end, ask ftell where you are, and divide by the size of one struct Player.

About Programming in C at UPI Study

Programming in C (Computer Science 240) is a self-paced online course of 78 video lessons in 11 chapters, from pseudocode and your first program to data types, decisions, loops, functions, arrays, strings, pointers, files, structures, dynamic memory and linked lists. It carries a NCCRS credit recommendation for 3 semester credits.

Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Compare: C vs C++

Why take it here

Why students take Programming in C with UPI Study

How programs work close to the machineProgramming in C teaches how a program uses memory: variables and data types, control flow, functions, arrays and strings, pointers, files, structures and dynamic memory. C is the base for operating systems, embedded devices and many computer-science courses.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Where the credit goes

Universities that work with NCCRS

Programming in C carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.

FAQ

Questions students ask us

About Workshop: Saving and Restoring Structures in Binary Files

How do you write a struct to a binary file in C?
Open the file with "wb", then call fwrite with the struct's address, its size, a count of 1, and the stream: fwrite(&hero, sizeof hero, 1, fp). A struct is one block of memory, so a single call copies every member. fwrite returns the number of items written, which should be 1. Reading it back uses fread with the same arguments on a file opened with "rb".
Why should you zero a struct before saving it to a file?
Starting from all zeros keeps leftover memory out of the file. A 16-character name array holding Mira uses only 5 places, counting the null character, and the unused places would otherwise hold whatever bytes were already in memory. Setting every byte to zero first, for example with memset, means the saved file contains only the data you meant to store.
Why does a struct with a char and an int take 8 bytes?
The compiler adds padding so the int starts at an address the processor handles well. The members total 5 bytes, but on a typical system the int must start at a multiple of 4, so three unused bytes follow the char and sizeof reports 8. offsetof, from stddef.h, shows the int starting at byte 4. Other compilers or machines may choose different padding.
Can a binary file of structs be read on a different computer?
Not reliably. The bytes depend on the program, the compiler, and the machine: int size, byte order, padding, and the member list can all differ. Even adding one member breaks an old loader, which silently reads the wrong bytes because the file has no labels. Raw struct files suit one program reading back its own data; for sharing, write text with fprintf or a format you define.

About the Programming in C course

How many college credits is Programming in C?
Programming in C (Computer Science 240) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does Programming in C cost and what is included?
$250, paid once, with lifetime access: all 78 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does Programming in C take?
It is self-paced with no deadlines. The 78 lessons total about 9 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

Ready for the full course? Earn 3 credits in Programming in C.

78 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.

Programming in C
3 credits · NCCRS
Enroll →