Non-Sequential File Access, Explained with Code Examples

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 →

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

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.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
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

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.

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?
Sequential access starts at the beginning of the file and reads past every earlier record, while direct access computes where a record lies and jumps straight to it. Reaching record 400 sequentially takes work proportional to its position. Direct access takes the same work for any record. It only works if every record is the same size.
How do seekg and seekp work, and what are ios::beg, ios::cur, and ios::end?
The function seekg moves a stream's get (read) marker, and seekp moves its put (write) marker. Each takes a byte offset from the start, or an offset measured from a landmark: ios::beg is the first byte, ios::cur is the current position, and ios::end is just past the last byte. On a file holding digits 0 through 9, seekg(3, ios::beg) makes the next read return 3. After seekg(0, ios::end), tellg() reports 10, the file size.
How do I calculate the offset of record n in a file of fixed-length records?
Multiply the record number by the size of one record, counting from zero: offset = n * sizeof(Member). Use sizeof rather than adding up field sizes, because padding changes the total. A record with an int, a char array of 32, and a double is typically 48 bytes, not 44. Record 10 then starts at byte 480, and in.seekg(10 * sizeof(Member)) jumps there.
How do I update one record in a binary file without rewriting the whole file?
Seek to the record, read it, change the fields, seek back to the same offset, then write it over the original. The second seek is the step people forget. The read moves the marker past the record, so without it the write overwrites the next record. On a stream open for both reading and writing, a seek is also required between a read and a write.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) 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 C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 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 C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 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 C++ Programming.

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

C++ Programming
3 credits · NCCRS
Enroll →