Scala File I/O

File I/O lets your program read data from files and write results back to disk. Scala uses Java's I/O libraries under the hood, but also provides its own cleaner API through scala.io.Source. Always close resources after use, or better — use automatic resource management patterns to ensure cleanup even when errors occur.

Reading a File

import scala.io.Source

// Read entire file as a string
val content = Source.fromFile("data.txt").mkString

// Read line by line
val lines = Source.fromFile("data.txt").getLines().toList

// With explicit close
val source = Source.fromFile("data.txt")
try
  val text = source.mkString
  println(text)
finally
  source.close()

File on disk: data.txt
      │
      ▼ Source.fromFile("data.txt")
Source (lazy reader)
      │
      ├── .mkString         → entire file as one String
      ├── .getLines()       → Iterator[String] (one per line)
      └── .close()          → release file handle

Safe File Reading with Try

import scala.io.Source
import scala.util.{Try, Using}

// Using (Scala 2.13+) — automatically closes the resource
def readFile(path: String): Try[String] =
  Using(Source.fromFile(path))(_.mkString)

def readLines(path: String): Try[List[String]] =
  Using(Source.fromFile(path))(_.getLines().toList)

readFile("config.txt") match
  case scala.util.Success(content) => println(content)
  case scala.util.Failure(ex)      => println(s"Could not read file: ${ex.getMessage}")

Writing to a File

import java.io.{FileWriter, PrintWriter}

// Write a string to file
def writeFile(path: String, content: String): Unit =
  val writer = new PrintWriter(new FileWriter(path))
  try writer.write(content)
  finally writer.close()

// Write lines to file
def writeLines(path: String, lines: List[String]): Unit =
  val writer = new PrintWriter(path)
  try lines.foreach(writer.println)
  finally writer.close()

writeFile("output.txt", "Hello from Scala!")
writeLines("names.txt", List("Alice", "Bob", "Carol"))

Appending to a File

import java.io.{FileWriter, PrintWriter}

def appendToFile(path: String, line: String): Unit =
  val writer = new PrintWriter(new FileWriter(path, true)) // true = append mode
  try writer.println(line)
  finally writer.close()

appendToFile("log.txt", "Server started at 09:00")
appendToFile("log.txt", "User logged in at 09:05")
appendToFile("log.txt", "Request processed at 09:06")

Reading CSV Data

import scala.io.Source
import scala.util.Using

case class Student(name: String, score: Int, grade: String)

def loadStudents(path: String): List[Student] =
  Using(Source.fromFile(path)) { source =>
    source.getLines()
      .drop(1)                          // skip header row
      .map(_.split(",").map(_.trim))    // split each line by comma
      .collect {
        case Array(name, score, grade) =>
          Student(name, score.toInt, grade)
      }
      .toList
  }.getOrElse(List.empty)

// Simulated: as if "students.csv" contained:
// Name,Score,Grade
// Alice,92,A
// Bob,78,B
// Carol,85,B

Writing CSV Data

import java.io.PrintWriter

def saveStudents(path: String, students: List[Student]): Unit =
  val writer = new PrintWriter(path)
  try
    writer.println("Name,Score,Grade")
    students.foreach { s =>
      writer.println(s"${s.name},${s.score},${s.grade}")
    }
  finally
    writer.close()

val students = List(
  Student("Alice", 92, "A"),
  Student("Bob", 78, "B"),
  Student("Carol", 85, "B")
)
saveStudents("output_students.csv", students)

Using for Automatic Resource Management

scala.util.Using is Scala's equivalent of Java's try-with-resources. It automatically calls close() on the resource when the block ends, even if an exception occurs:

import scala.util.Using
import scala.io.Source
import java.io.PrintWriter

// Read with auto-close
val lines = Using(Source.fromFile("input.txt")) { src =>
  src.getLines().toList
}

// Write with auto-close
Using(new PrintWriter("result.txt")) { writer =>
  writer.println("Line 1")
  writer.println("Line 2")
  writer.println("Line 3")
}

// Use multiple resources together
val result = Using.Manager { use =>
  val reader = use(Source.fromFile("input.txt"))
  val writer = use(new PrintWriter("output.txt"))
  reader.getLines().foreach(writer.println)
}

Checking File Existence

import java.io.File

val f = new File("data.txt")
println(f.exists())    // true or false
println(f.isFile())    // true if it's a file (not directory)
println(f.length())    // file size in bytes
println(f.getName())   // "data.txt"
println(f.getParent()) // parent directory path

// List files in a directory
val dir = new File(".")
dir.listFiles().filter(_.isFile).foreach { f =>
  println(f.getName)
}

Reading from URL

import scala.io.Source

val url = "https://www.example.com"
val html = Source.fromURL(url).mkString
println(html.take(200))   // first 200 characters of the page

File I/O Summary


Task                         Code
───────────────────────────  ─────────────────────────────────────────
Read entire file             Source.fromFile(path).mkString
Read lines                   Source.fromFile(path).getLines().toList
Safe read                    Using(Source.fromFile(path))(_.mkString)
Write file                   PrintWriter(path).println(content)
Append to file               FileWriter(path, true) → PrintWriter
Check exists                 new File(path).exists()
Auto-close resource          scala.util.Using { }

Always close file handles — unclosed files can cause data corruption, resource leaks, and OS-level errors. Prefer Using for any file operation so resources are guaranteed to close regardless of what happens inside the block.

Leave a Comment

Your email address will not be published. Required fields are marked *