Aiming for Jarvis, Creating D.A.N.I.

Tutorial 20: Reading and writing CSV (or, Dealing with the data format that refuses to die)

If there is one truth in software development, it is this: no matter how fancy your internal data structures are, at some point, someone is going to hand you a CSV file. It’s the "Excel spreadsheet" of the programming world—a format that is deceptively simple and almost universally hated, yet entirely unavoidable.

In Skink, we handle this with std/csv. It’s not elegant, but it gets the job done.

Reading CSV

When you're faced with a wall of comma-separated text, csv.NewReader is your entry point. It turns that raw string into something you can iterate through row by row.

module main

import "std/csv"

fn main() -> int {
    data := "name,age\nAlice,30\nBob,25\n"
    reader := csv.NewReader(data)
    
    for {
        rec, err := reader.Read()
        
        // When there's no more data, we get a non-empty error message
        if err.message != "" {
            break
        }
        
        name, _ := rec.Get(0)
        age, _ := rec.Get(1)
        print("{name} is {age}")
    }
    return 0
}

Keep in mind that Read() is a bit of a classic-style iterator. Check that error message—it’s not a failure, it’s just the polite way of saying "I'm out of rows, stop asking."

Working with fields

A Record gives you the tools to peek inside the row. Don't go assuming every row has the same number of columns, though—the real world is a messy place, and your CSVs will be too.

reader := csv.NewReader("name,age\nAlice,30\n")
rec, _ := reader.Read()
print("columns: {rec.Len()}")

Writing CSV

Need to send data out? csv.NewWriter lets you piece together your own CSV files. It’s manual work, but it’s safer than just concatenating strings and hoping the user doesn't have a comma in their name.

import "std/csv"

fn main() -> int {
    w := csv.NewWriter()
    
    // You'll often be passing records back out from a reader
    rec, _ := csv.NewReader("header1,header2").Read()
    w.Write(rec)
    
    print(w.String())
    return 0
}

Exercises

Don't let the legacy formats get you down—try these:

  1. The Average Joe: Parse a CSV string with a numeric column and calculate the average. Don't forget to use std/str to cast those strings into numbers.
  2. The File-Pipe: Combine what we learned in Tutorial 10 with this one. Read a real CSV file from your disk and print the data.
  3. The Converter: Write a program that takes a CSV and spits out JSON. It’s the kind of utility script that eventually becomes the most important tool in your folder.

Next

When you're ready to get down to the metal and start talking to the C world (or if you’re just a glutton for punishment), we'll talk about C interoperability.