diff --git a/src/main.rs b/src/main.rs
index dfa92baac002dea5a93fec027b0f7066abd7e867..52c070d4f036364d85967750c203386476fae0ac 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,20 +1,25 @@
 mod undirected_graph;
 use std::collections::HashMap;
 use std::env;
+use std::fs::File;
+use std::io::{Seek, Write};
 use std::process;
 use undirected_graph::UndirectedGraph;
 
-fn main() {
+fn main() -> std::io::Result<()> {
     let args: Vec<String> = env::args().collect();
 
-    if args.len() != 2 {
-        eprintln!("Usage: {} <number-of-spokes>", args[0]);
+    if args.len() != 3 {
+        eprintln!(
+            "Usage: {} <number-of-spokes-in-wheel> <sparse-matrix-filename>",
+            args[0]
+        );
         process::exit(1);
     }
 
     let num_spokes_maybe: Result<usize, std::num::ParseIntError> = args[1].parse::<usize>();
     if num_spokes_maybe.is_err() {
-        eprintln!("Error parsing the first argument as number-of-spokes.");
+        eprintln!("Error parsing the first argument as a natural number.");
         process::exit(1);
     }
     let num_spokes: usize = num_spokes_maybe.unwrap();
@@ -24,6 +29,14 @@ fn main() {
         process::exit(1);
     }
 
+    let sparse_matrix_filename: &String = &args[2];
+    let sparse_matrix_file_res: Result<File, std::io::Error> = File::create(sparse_matrix_filename);
+    if sparse_matrix_file_res.is_err() {
+        eprintln!("Error opening file: {}", sparse_matrix_filename);
+        process::exit(1);
+    }
+    let mut sparse_matrix_file: File = sparse_matrix_file_res.unwrap();
+
     let mut cocycle_graphs: Vec<UndirectedGraph> = vec![];
     let mut cocycle_graph_index: HashMap<UndirectedGraph, usize> = HashMap::new();
     let mut cocycle_graph_vertex_orbits: Vec<HashMap<usize, usize>> = vec![];
@@ -44,7 +57,10 @@ fn main() {
     cocycle_graph_index.insert(wheel_graph_normal.clone(), 0);
     cocycle_graph_vertex_orbits.push(wheel_graph_vertex_orbits);
 
-    println!("? ? M");
+    // Write a placeholder for the header.
+    let header_line_length: usize = 64;
+    writeln!(sparse_matrix_file, "{}", "x".repeat(header_line_length))?;
+
     let mut g_idx: usize = 0;
     loop {
         // dbg!(&g_idx);
@@ -65,7 +81,7 @@ fn main() {
                 idx
             };
             // TODO: Make the output lexicographically ordered? Strictly speaking this is not the SMS format right now.
-            println!("{} {} {}", dg_idx + 1, g_idx + 1, c);
+            writeln!(sparse_matrix_file, "{} {} {}", dg_idx + 1, g_idx + 1, c)?;
 
             let cg_data: HashMap<UndirectedGraph, HashMap<usize, usize>> =
                 dg.contractions(&dg_edge_orbits);
@@ -86,13 +102,15 @@ fn main() {
             break;
         }
     }
-    println!("0 0 0");
-    println!("# Move this line to the top:");
-    println!(
+    writeln!(sparse_matrix_file, "0 0 0")?;
+    sparse_matrix_file.rewind()?;
+    let mut header_line: String = format!(
         "{} {} M",
         cocycle_differential_graphs.len(),
         cocycle_graphs.len()
     );
+    header_line += &" ".repeat(header_line_length - header_line.len());
+    writeln!(sparse_matrix_file, "{}", header_line)?;
 
     eprintln!(
         "Matrix size: {} x {}",
@@ -101,4 +119,6 @@ fn main() {
     );
 
     // TODO: Also output the ordered bases of graphs.
+
+    Ok(())
 }