Exercise: File I/O
Read a school's grades from a CSV file with mistakes in it, log every line you can't read with your own LogService, write an honor roll, and add new students to the end of a file.
Journeyman · C# · Updated
A school keeps its students' grades in a CSV file exported from a spreadsheet. Like most real files, it has mistakes in it: a line with a missing column, a GPA of n/a, a blank line at the end. You'll write the code that reads it anyway, logs what it can't read, and writes new files from it.
Get the exercise code
Open this lesson's GitHub repository, github.com/ask-codey/exercise-file-i-o, also linked from the Exercise box beside the lesson. Click Code, then Download ZIP, and unzip it into your bootcamp folder. Or clone it with Git. Then open GradeBook.slnx in Visual Studio.
| File | What's in it |
|---|---|
GradeBook/data/student_grades.csv |
The school's file, mistakes and all. It's set to Copy if newer, so it's copied next to the program when it builds. |
GradeBook/Student.cs, IClock.cs, SystemClock.cs |
Finished |
GradeBook/LogService.cs |
A log file per day, for you to finish |
GradeBook/GradeFile.cs |
Reads and writes the CSV files, for you to finish |
GradeBook.Tests |
Tests for both. They work in a temporary folder, with a fake clock. |
The requirements are in the comment at the top of each file you finish.
What to do
| Member | What it does |
|---|---|
LogService.CurrentFilePath |
Today's file in the log folder, such as logs\errors\20260314.log |
LogService.Log(message) |
Appends 2026-03-14 21:05:09 message, creating the folder and file if needed, and never crashing the app |
GradeFile.Read(path) |
The students in the file. Skips the header and blank lines; skips and logs each bad line with its line number; logs a missing file and returns an empty list. |
GradeFile.WriteHonorRoll(path, students, minimumGpa) |
A new file with the header and every student at or above the minimum |
GradeFile.AddStudent(path, student) |
One line at the end of the file, with the header first if the file is new |
Run the program with Ctrl+F5, and the tests with Test > Run All Tests.
Hints
- Start with
LogService.Readlogs through it, and its tests are the simplest. - Dates:
{clock.Now:yyyyMMdd}for the file name and{clock.Now:yyyy-MM-dd HH:mm:ss}for an entry. CapitalHHis the 24-hour clock; capitalMMis the month. - Count the lines in
Readas you go, starting from 1 for the header, so a logged line number matches what you'd see in an editor. - A bad line is expected, not exceptional: check it with
columns.Lengthanddecimal.TryParse. A missing file is the one thing tocatch. - Replace or append?
WriteHonorRollreplaces;AddStudentappends. CheckFile.Existsbefore opening the writer, to know whether a new file needs its header.
When you're done
Every test passes, and the program prints (with today's date):
Read 8 students
firstname,lastname,gpa
Emily,Wilson,3.91
Jane,Garcia,3.96
James,Miller,3.85
Problems logged in logs\errors\20260314.log:
2026-03-14 13:34:28 student_grades.csv line 7: can't read 'David,Jones'
2026-03-14 13:34:28 student_grades.csv line 10: can't read 'Michael,Davis,n/a'
Open student_grades.csv and check lines 7 and 10: that's what a good log does, it sends you straight to the problem.
Submit your exercise
The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.
On GitHub, click +, then New repository. Name it (for example
exercise-file-i-o), choose Public, and click Create repository. Leave out the README: your folder already has one.In a terminal in your exercise folder (Git Bash on Windows), send your work to your new repo. If you downloaded the ZIP:
git init -b main git add . git commit -m "My solution" git remote add origin https://github.com/your-name/exercise-file-i-o.git git push -u origin mainIf you cloned the starter instead, point your copy at your own repo, then commit and push:
git remote set-url origin https://github.com/your-name/exercise-file-i-o.git git add . git commit -m "My solution" git push -u origin mainPaste your repo's address, such as
https://github.com/your-name/exercise-file-i-o, into Submit your exercise on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.
Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.
So what
Real files are messy. Code that reads the good lines, logs the bad ones with enough detail to fix them, and never crashes over a missing file is code people can trust with their data.
Key terms
- CSV File
- StreamReader
- Append
- Logging