Lesson 33 · File I/O & JSON

File I/O & JSON

Read and write text files, CSV data, and JSON with System.IO and System.Text.Json — the building blocks of settings files, export features, and data interchange.

Key Takeaway: For text files use File.WriteAllText / File.ReadAllText (simple, one-shot) or StreamWriter / StreamReader (line-by-line, large files). For CSV, split each line on commas and trim quotes. For JSON, use JsonSerializer.Serialize(obj) to write and JsonSerializer.Deserialize(Of T)(json) to read — no third-party libraries needed in .NET 10. Always use Application.LocalUserAppDataPath as the base folder for data files so your app works without admin rights.
File.WriteAllText
System.IO.File
Write an entire string to a file in one call. Creates or overwrites.
File.ReadAllText
System.IO.File
Read the whole file as a single string. Fine for small files.
File.ReadAllLines
System.IO.File
Read all lines into String(). Good for structured text/CSV.
StreamWriter
System.IO
Write line by line. Efficient for large files. Use in a Using block.
StreamReader
System.IO
Read line by line with ReadLine(). Returns Nothing at end of file.
JsonSerializer
System.Text.Json
Serialize(obj) → JSON string. Deserialize(Of T)(json) → typed object.
Path.Combine
System.IO.Path
Build paths safely: Path.Combine(folder, "data.json"). Never concatenate path strings manually.
LocalUserAppDataPath
Application
Per-user writable folder — no admin rights needed. Use as your app's data root.

33.1 Reading and Writing Text Files

Use System.IO.File's one-shot methods for small files and StreamReader/StreamWriter for line-by-line processing of larger ones. Always wrap in Using to ensure the file handle is closed even on exceptions.

TextIO.vb — Visual Basic 2026
Imports System.IO

' --- Safe base folder (no admin rights needed) ---
Dim dataDir = Application.LocalUserAppDataPath
Directory.CreateDirectory(dataDir)   ' ensure it exists
Dim filePath = Path.Combine(dataDir, "notes.txt")

' ═══ ONE-SHOT (small files) ═══
File.WriteAllText(filePath, txtNotes.Text)                         ' write whole file
Dim content = File.ReadAllText(filePath)                          ' read whole file
Dim lines() = File.ReadAllLines(filePath)                         ' read into String array
File.AppendAllText(filePath, Environment.NewLine & "New line")  ' append

' ═══ STREAMING (large files, line-by-line) ═══
Using sw As New StreamWriter(filePath, append:=False)  ' overwrite
    sw.WriteLine("StudentID,Name,Grade,Class")         ' header
    For Each s In students
        sw.WriteLine($"{s.StudentID},{s.Name},{s.Grade},{s.Class}")
    Next
End Using   ' file closed here even if exception occurs

Using sr As New StreamReader(filePath)
    Dim header = sr.ReadLine()     ' skip header row
    Dim line = sr.ReadLine()
    Do While line IsNot Nothing
        Dim parts = line.Split(","c)
        If parts.Length = 4 Then
            Dim s As New Student With {
                .Name  = parts(1).Trim(),
                .Grade = CDbl(parts(2)),
                .Class = parts(3).Trim()
            }
            students.Add(s)
        End If
        line = sr.ReadLine()
    Loop
End Using

' --- Check existence before reading ---
If File.Exists(filePath) Then
    content = File.ReadAllText(filePath)
Else
    MessageBox.Show("File not found.")
End If

33.2 CSV Import and Export

CSV (Comma-Separated Values) is the simplest interchange format — readable by Excel, importable by databases, and trivial to write. Quote fields that may contain commas. For production use, consider a dedicated CSV library, but for school projects the manual approach below is sufficient.

CSV.vb — Visual Basic 2026
' --- Export List(Of Student) to CSV ---
Private Sub ExportCSV(path As String, students As List(Of Student))
    Using sw As New StreamWriter(path, append:=False, encoding:=Text.Encoding.UTF8)
        sw.WriteLine("StudentID,Name,Grade,Class")
        For Each s In students
            ' Quote name in case it contains a comma
            sw.WriteLine($'{s.StudentID},"{s.Name}",{s.Grade},{s.Class}')
        Next
    End Using
    MessageBox.Show($"Exported {students.Count} rows to {path}")
End Sub

' --- Import CSV → List(Of Student) ---
Private Function ImportCSV(path As String) As List(Of Student)
    Dim result As New List(Of Student)
    Dim lines = File.ReadAllLines(path)
    For i = 1 To lines.Length - 1   ' skip header (index 0)
        Dim parts = lines(i).Split(","c)
        If parts.Length < 4 Then Continue For
        Dim grade As Double
        If Not Double.TryParse(parts(2), grade) Then Continue For
        result.Add(New Student With {
            .StudentID = CInt(parts(0)),
            .Name      = parts(1).Trim(""""c),  ' strip surrounding quotes
            .Grade     = grade,
            .Class     = parts(3).Trim()
        })
    Next
    Return result
End Function

' --- OpenFileDialog integration ---
Private Sub btnImport_Click(...)
    Using dlg As New OpenFileDialog()
        dlg.Filter  = "CSV files|*.csv|All files|*.*"
        dlg.Title   = "Import Students from CSV"
        If dlg.ShowDialog() = DialogResult.OK Then
            students = ImportCSV(dlg.FileName)
            _bs.DataSource = students.ToList()
            MessageBox.Show($"Imported {students.Count} students.")
        End If
    End Using
End Sub

33.3 JSON with System.Text.Json

JSON is the standard format for configuration files, API responses, and data interchange. .NET 10 includes System.Text.Json in the base library — no NuGet package needed. Use JsonSerializerOptions with WriteIndented = True for human-readable output.

JSON.vb — Visual Basic 2026
Imports System.Text.Json

' --- Serialize: object → JSON string ---
Dim opts As New JsonSerializerOptions() With {.WriteIndented = True}
Dim json = JsonSerializer.Serialize(students, opts)
' Result:
' [
'   { "StudentID": 1, "Name": "Ahmad Farid", "Grade": 88, "Class": "4A" },
'   ...
' ]

' --- Write to file ---
File.WriteAllText(Path.Combine(dataDir, "students.json"), json)

' --- Deserialize: JSON string → typed object ---
Dim loaded = JsonSerializer.Deserialize(Of List(Of Student))(
    File.ReadAllText(Path.Combine(dataDir, "students.json")))

' --- Application settings pattern ---
Public Class AppSettings
    Public Property LastOpenedFile As String
    Public Property Theme          As String = "Light"
    Public Property MaxResults     As Integer = 100
End Class

Private _settingsPath = Path.Combine(Application.LocalUserAppDataPath, "settings.json")

Function LoadSettings() As AppSettings
    If Not File.Exists(_settingsPath) Then Return New AppSettings()
    Try
        Return JsonSerializer.Deserialize(Of AppSettings)(File.ReadAllText(_settingsPath))
    Catch
        Return New AppSettings()   ' corrupt file → fresh defaults
    End Try
End Function

Sub SaveSettings(s As AppSettings)
    File.WriteAllText(_settingsPath,
        JsonSerializer.Serialize(s, New JsonSerializerOptions With {.WriteIndented=True}))
End Sub
Try It — Simulation 33.1: Text File Read & Write

Type in the editor, click Save to write to the virtual file, and Read to load it back. Append adds to the existing content. The file display shows the raw bytes as they'd appear on disk.

StreamWriter / StreamReader — notes.txt
Editor (txtNotes.Text):
File on disk (notes.txt):
— file empty —

Try It — Simulation 33.2: CSV Export & Import

Export the student list to a virtual CSV file. Edit the CSV text manually, then import it back — the grid updates to reflect any changes you made.

CSV Export / Import — students.csv
CSV file content (editable):
Imported data grid:
— export then import —

Try It — Simulation 33.3: JSON Serialise & Deserialise

Serialise the student list to JSON with JsonSerializer.Serialize, edit the JSON, and deserialise back. Also try the AppSettings pattern — save and load a settings object.

JsonSerializer.Serialize / Deserialize — students.json
JSON output (editable):
Deserialised objects:
— deserialise to see data —

33.4 GitHub Copilot — JSON Settings Manager

GitHub Copilot — persist app settings to JSON
You typed: ' Generate a generic settings manager that uses System.Text.Json to load and save any serialisable class to a JSON file in LocalUserAppDataPath. Include a LoadOrDefault(Of T) function that returns a new T() if the file is missing or corrupt.'
Imports System.IO, System.Text.Json

Module SettingsManager
    Private _opts As New JsonSerializerOptions() With {.WriteIndented = True}

    Function LoadOrDefault(Of T As New)(fileName As String) As T
        Dim path = Path.Combine(Application.LocalUserAppDataPath, fileName)
        If Not File.Exists(path) Then Return New T()
        Try
            Dim json = File.ReadAllText(path)
            Return JsonSerializer.Deserialize(Of T)(json) ?? New T()
        Catch
            Return New T()   ' corrupt JSON → safe default
        End Try
    End Function

    Sub Save(Of T)(fileName As String, obj As T)
        Dim path = Path.Combine(Application.LocalUserAppDataPath, fileName)
        Directory.CreateDirectory(Path.GetDirectoryName(path))
        File.WriteAllText(path, JsonSerializer.Serialize(obj, _opts))
    End Sub
End Module

' --- Usage ---
Dim settings = SettingsManager.LoadOrDefault(Of AppSettings)("settings.json")
settings.Theme = "Dark"
SettingsManager.Save("settings.json", settings)

Lesson Summary

  • Use File.WriteAllText / ReadAllText for small, whole-file operations and StreamWriter / StreamReader in Using blocks for line-by-line processing of larger files.
  • Always build file paths with Path.Combine and store data files under Application.LocalUserAppDataPath — this is a per-user folder that never requires admin rights.
  • For CSV, write a header row first, then one row per record. On import, split on commas, skip the header (index 0), validate each field with TryParse, and skip malformed lines with Continue For.
  • JsonSerializer.Serialize(obj, opts) converts any class or collection to a JSON string. Deserialize(Of T)(json) rebuilds the typed object. Set WriteIndented = True for human-readable files.
  • Wrap Deserialize in Try/Catch and return a New T() on failure — JSON files can be hand-edited and become corrupt.
  • Check File.Exists(path) before reading. Use Directory.CreateDirectory(dir) before writing — it is a no-op if the folder already exists.

Exercises

Exercise 33.1 — Student CSV Import/Export

  • Add Export CSV and Import CSV buttons to the student form from Lesson 31. Export uses SaveFileDialog; import uses OpenFileDialog.
  • On import, validate each row: StudentID must parse as Integer, Grade 0–100, Name non-empty. Collect all validation errors and show them in a summary MessageBox.
  • Copilot challenge: "Generate a Sub that reads a CSV file asynchronously using File.ReadAllLinesAsync, processes each line with LINQ, and shows a ProgressBar as rows are added to the DataTable"

Exercise 33.2 — JSON Settings File

  • Create an AppSettings class: LastOpenedFile, WindowWidth, WindowHeight, DefaultClass, AutoSave (Boolean). Persist it to settings.json in LocalUserAppDataPath.
  • On Form_Load call LoadOrDefault. On Form_Closing save settings. Test that window size is remembered across runs.
  • Copilot challenge: "Extend AppSettings to store a RecentFiles property as List(Of String) (max 10). Show the list in a ToolStripMenuItem submenu on a File menu."

Next: Lesson 34 — Async Programming

Keep your UI responsive during long-running operations with Async/Await, Task(Of T), and IProgress(Of T).

Continue »

Related Resources


Featured Books

Visual Basic 2022 Made Easy

Visual Basic 2022 Made Easy

by Dr. Liew Voon Kiong

File I/O chapters: reading, writing, CSV parsing, and application settings patterns.

View on Amazon →