UPI Study › Courses › C++ Programming › Free lessons › Lesson 10.1 Free with a free account
Non-Sequential File Access
C++ Programming · Chapter 10: File Access and MemorySection 10.1 · lesson 69 of 84video coming soon
← Applied Challenge: Student Record SystemNext lesson: Decimal and Text in File Streams →
In this lesson
Jumping directly to specific records.
- Tell sequential from direct access, and what each costs
- Move the get and put markers with seekg and seekp
- Design a fixed-length record and compute its offset
- Update one record in place, safely
Transcript
Everything said in the video, section by section (1,628 words). Read along, or search it.
Opening Problem
Reaching One Record Among Thousands
Reading a file from the beginning is fine, until the file holds fifty thousand records, and you want the four hundredth. A file isn't really a stream of text arriving in order. It's a numbered run of bytes, and the stream keeps a marker saying where it is. Move the marker, and you can read or overwrite any record without touching the rest. The whole technique rests on one condition: every record must be the same size.
Two Approaches
Sequential Versus Direct Access Compared
There are two ways to reach the four hundredth record. Sequential access means starting at the beginning, and passing over everything on the way. Every record in between is read, and discarded. Direct access, also called random access, though nothing about it is random, means computing where the record lies, and going straight there. The position is computed: four hundred times the size of one record. That's not a small improvement. It's the difference between work in proportion to the record's position, and work that doesn't depend on it at all.
Stream Markers
Get and Put Positions Explained
Every stream keeps track of where it is. A stream you read from has a get position. A stream you write to has a put position. One opened for both has one of each. A read or a write happens at the marker, then moves it forward by however many bytes were transferred. Seek g moves the read marker, either to a byte counted from the start, where the first byte is zero, or relative to a landmark. Seek p does the same for the write marker. And tell g and tell p report where each marker currently sits, as a byte position from the start.
Seek Landmarks
Measuring From Beg, Cur, and End
There are three landmarks to measure from. Beg is the first byte of the file. Cur is wherever the marker is now. End is one past the last byte. Run it on a file holding the ten digits, zero to nine. Seek to byte three, and the next byte read is a three. Reading moved the marker on to four. Now seek two from cur. Four plus two is six, so a six comes back. Minus one from the end is the last byte, a nine. And zero from the end is just past it, which is the file's size: ten. That's how you measure a file. Seek to the end, take the position, and seek back to the start. With forty-eight-byte records, forty-eight from cur skips forward one record, and minus forty-eight steps back one. Minus forty-eight from the end is the start of the last record.
Counting Records
Dividing File Size by Record Size
With equal-sized records, the count is the size divided by one record's size. If that division leaves a remainder, the file isn't what you think it is. Something else wrote it, or a write was interrupted part-way.
Fixed Size Cells
Why Records Must Share One Width
Finding where record n starts is only possible if every record occupies the same number of bytes. That rules out storing text of varying length directly. A name of seven letters, and one of twenty, can't both be found by multiplication. So a member record holds an int I D, a fixed block of thirty-two characters for the name, and a double balance. Picture the file as a strip of equal cells. Record zero starts at byte zero, record one at forty-eight, and so on. A record's start is its number multiplied by the cell width. Record three starts at three times forty-eight, which is one hundred forty-four.
Memory Layout
Padding Makes Forty-Eight Bytes
Here's the layout of one member on a typical machine. The I D takes four bytes, starting at zero. The name takes thirty-two, always, however short the name, starting at four. Then four bytes of padding, inserted so the next field starts at a convenient boundary. Then the balance, eight bytes, starting at forty. The whole record is forty-eight bytes, which is what size of member reports. That padding is why four plus thirty-two plus eight, forty-four, is the wrong answer. The amount depends on the machine and the settings. So always write size of member, for both the offset arithmetic and the transfer size. A hand-written constant is one settings change away from being wrong.
Quick Check
Where Record Ten Starts
Quick check. With forty-eight-byte records, where does record ten start? Pause and work it out. At byte four hundred eighty. Ten times forty-eight. One multiplication, and no reading.
Raw Transfer
Read, Write, and Reinterpret Cast
The functions that move raw records are read and write. Both deal in bytes, and take two arguments: where the bytes are, and how many. Because they expect a byte-level view, the record's storage is presented as bytes with reinterpret cast. It says treat this storage as a run of characters, without altering a thing. Here, a member is written out, forty-eight bytes, then read back into another member. G count reports how many bytes the read actually got, so an incomplete record can be detected.
Limits
Only Plain Records Can Be Copied
This copies a record's storage verbatim, so it only works for plain records: numbers, fixed blocks of characters, and records made of those. A growable text type must never appear in one. What would be written is its internal bookkeeping, not the letters, and reading it back produces nonsense at best. And a file written this way isn't portable between machines. If it must be, a text format is the answer.
Reading Code
Compute, Seek, Read a Record
Reading record n takes three steps: compute, seek, read. The offset is the index times the size of a member. Seek g jumps straight to it, and read transfers one record. Then it returns whether g count equals a whole record. Two habits are built into those lines. The offset comes from size of, rather than a written number, so it can't drift out of step with the record. And the result is checked, not assumed. Asking for record nine hundred of a five-record file doesn't fail loudly. It simply transfers nothing, and that check turns it into an answer you can act on. One more point: after a short read like that, the stream is left in a failed state, so clear it before using it again.
Update in Place
Five Steps to Change One Record
Here's the payoff. To change one record in a large file, you don't rewrite the file. Seek to the record. Read it. Change what you want. Seek back to the same place. And write it out over the top. Five steps, and the fourth is the one people leave out. The read in step two already moved the marker past the record. Skip the second seek, and the new data lands on the record after the one you meant.
Code Walkthrough
Rewriting a Balance and Appending
So after changing the balance, seek p goes back to the same offset, then the record is written, and the stream is flushed. Run it: Dev goes from fifteen twenty point five to sixteen twenty point five, and Zoya, the next record, is untouched. Appending is one more line. Seek the put marker to the end, just past the last byte, and write. To count, seek the get marker to the end, and divide its position by the size of one record. Six records now: five, and Kofi at the end.
Marker Trace
Following Positions Through an Update
Follow the markers while updating record three, with forty-eight-byte records. Seeking to three times forty-eight puts the marker at one hundred forty-four. Reading forty-eight bytes moves it to one hundred ninety-two. Seeking back puts it at one hundred forty-four again. Writing forty-eight bytes moves it to one hundred ninety-two. Had that seek been omitted, the write would have started at one hundred ninety-two, overwriting record four. A file stream opened both ways shares one position between its get and put sides, which is why both numbers move together.
Stricter Rule
Seek Between Reading and Writing
And there's a stricter rule. On a stream open for both reading and writing, a read must be followed by a seek before a write, and a write by a seek before a read. Going straight from one to the other is undefined behavior, so the program may work today, and misbehave after an unrelated change. Make the seek a reflex.
Common Mistakes
Faults and Their Causes
Here are faults worth recognizing. The wrong record overwritten means no seek between the read and the write. Every record after the first coming back as rubbish means an offset using a hand-written size that ignores padding. Use size of everywhere. Names coming back garbled means a growable text type inside the record. Use a fixed block of characters. Reading past the end returning stale data means the read's result was never checked. Compare g count against the record size. Changes missing after the program ends means buffered output was never sent. Flush, or let the stream close normally. And a record count with a remainder should be reported, not ignored.
Key Terms
Vocabulary for Direct File Access
A few key terms. Sequential access reaches data by passing over everything before it. Direct access computes its position, and goes straight there. The get position is where the next read happens. The put position is where the next write happens. An offset is a byte distance from a landmark. A fixed-length record occupies the same number of bytes, whatever it holds. And an update in place overwrites one record where it sits, leaving the rest of the file untouched.
Think About It
A Wrong Size Misaligns Reads
Here's something to think about. A program's record size is really forty-eight bytes, but it has the number forty-four typed in. It seeks to record five. Where does the read begin? Pause and think. At byte two hundred twenty, five times forty-four. Record four starts at one hundred ninety-two, so the read begins twenty-eight bytes inside it, and every field comes back misaligned.
Key Takeaways
Summary of Direct Access Rules
To summarize. Direct access needs every record to be the same size, and finds record n at n times the size of one record. Use only plain fields, with fixed character blocks rather than growable text, and use size of, never a hand-written total. Check g count after every read. And seek again between a read and a write.
About C++ Programming at UPI Study
C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. 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.
Enroll now → Course details Download the syllabus Every course with PRO →
Why take it here
Why students take C++ Programming with UPI Study
Where the credit goes
Universities that work with NCCRS
C++ Programming 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.
Thomas Edison State UniversitySigned partner
University of the PeopleSigned partner
Charter Oak State CollegeSigned partner
Strayer UniversitySigned partner
Columbia Southern UniversitySigned partner
Indiana TechSigned partner
Penn StateWorks with NCCRS
Southern New Hampshire UniversityWorks with NCCRS
SUNYWorks with NCCRS
+many more cooperating universitiesFind my college →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 Non-Sequential File Access
What is the difference between sequential and direct access in C++ file handling?
How do seekg and seekp work, and what are ios::beg, ios::cur, and ios::end?
How do I calculate the offset of record n in a file of fixed-length records?
How do I update one record in a binary file without rewriting the whole file?
About the C++ Programming course
How many college credits is C++ Programming?
How much does C++ Programming cost and what is included?
Which universities accept UPI Study credits?
How long does C++ Programming take?
How are the exams done?
How do my credits reach my college?
Ready for the full course? Earn 3 credits in C++ Programming.
84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.
3 credits · NCCRSEnroll →