Skip to content

Scala 文件 I/O

Scala 中的文件输入/输出 (I/O) 通常涉及使用 Java 的 java.io 类,但会封装 Scala 特性以实现更好的资源管理和集成。scala.io.Source 对象提供了方便的方式来读取文件,而像 os-lib 这样的库提供了更符合 Scala 习惯的 API,尽管 Java 互操作性完全可行。

使用 java.io.PrintWriter 和 java.io.FileWriter 很常见。正确管理资源至关重要,要确保即使发生错误,文件也能被关闭。推荐使用 scala.util.Using (Scala 2.13+)。

import java.io.{File, PrintWriter, FileWriter}
import scala.util.{Try, Using}
@main def WriteFileDemo(): Unit = {
val fileName = "output.txt"
val content = "Hello from Scala!\nThis is line 2."
val result: Try[Unit] = Using(new PrintWriter(new FileWriter(new File(fileName)))) { writer =>
writer.println(content) // println adds a newline
writer.write("This uses write.")
println(s"Successfully wrote to $fileName")
}
result.recover { // Handle potential errors during file writing/closing
case e: Exception => println(s"Error writing to file $fileName: ${e.getMessage}")
}
}

这段代码尝试写入 output.txt。Using 确保 PrintWriter(以及底层的 FileWriter)自动关闭。Try 包装器允许优雅地处理潜在的 IOExceptions。

要从控制台(标准输入)读取输入,请使用 scala.io.StdIn。

import scala.io.StdIn
@main def ReadInputDemo(): Unit = {
print("Please enter your name: ")
val name = StdIn.readLine()
print("Please enter your age: ")
val age = StdIn.readInt() // Or readLine() and convert with .toIntOption
println(s"\nThanks, $name! You are $age years old.")
}

运行此代码,它会提示你输入:

$ scala ReadInputDemo
Please enter your name: Scala User
Please enter your age: 5
Thanks, Scala User! You are 5 years old.

StdIn 提供了各种方法,例如 readLine()、readInt()、readDouble() 等。

scala.io.Source 提供了方便的方式来读取文件内容。同样,适当的资源管理至关重要。

import scala.io.Source
import scala.util.Using
import java.nio.charset.StandardCharsets // Specify encoding
@main def ReadFileLinesDemo(): Unit = {
val fileName = "output.txt" // Use the file created earlier
println(s"Reading content from $fileName:")
val linesResult: Try[List[String]] = Using(Source.fromFile(fileName, StandardCharsets.UTF_8.name())) { source =>
source.getLines().toList // Read all lines into a List
}
linesResult match {
case scala.util.Success(lines) =>
lines.zipWithIndex.foreach { case (line, index) =>
println(f"${index + 1}%2d: $line")
}
case scala.util.Failure(ex) =>
println(s"Error reading file: ${ex.getMessage}")
}
}

输出(基于之前的写入示例):

Reading content from output.txt:
1: Hello from Scala!
2: This is line 2.
3: This uses write.
import scala.io.Source
import scala.util.Using
@main def ReadFileStringDemo(): Unit = {
val fileName = "output.txt"
val contentResult: Try[String] = Using(Source.fromFile(fileName)) { source =>
source.mkString // Read the entire file into a single String
}
contentResult match {
case scala.util.Success(content) =>
println(s"\n-- File content as single string --\n$content")
case scala.util.Failure(ex) =>
println(s"Error reading file: ${ex.getMessage}")
}
}
  • 资源管理: 始终确保文件/流被关闭。scala.util.Using 是最佳实践。
  • 错误处理: 文件操作可能会失败。使用 Try 或 Either 来优雅地处理潜在的 IOExceptions。
  • 字符编码: 注意字符编码(例如,UTF-8)。如果与平台默认编码不同,请在读取/写入时指定。
  • 库: 对于更复杂的文件系统操作(列出目录、复制、删除、监视文件),考虑使用像 Li Haoyi 的 os-lib 这样的库,它提供了比原生 Java 互操作性更符合 Scala 习惯的 API。