在 Scala 中进行文件读写,主要有两种常用方式:一是利用 Scala 标准库中封装的 Java IO 操作 (如 java.io.File、BufferedReader、PrintWriter 等),二是使用 Scala 专门的文件操作工具类 (如 scala.io.Source 用于读取,scala.tools.nsc.io.File 用于增强写操作),此外还可以结合第三方库(如 Akka Stream、FS2)处理大文件或流式场景。
一、文件读取(核心:scala.io.Source)
scala.io.Source 是 Scala 标准库中用于读取文本文件的核心工具,支持读取本地文件、URL、输入流等,操作简洁。
1. 读取整个文件为字符串
scala
java
import scala.io.Source
object FileReadDemo {
def main(args: Array[String]): Unit = {
// 文件路径(相对路径或绝对路径)
val filePath = "test.txt"
// 方式1:直接读取(需手动关闭资源)
val source = Source.fromFile(filePath, "UTF-8") // 第二个参数指定编码
try {
val content = source.mkString // 读取整个文件为字符串
println("文件内容:")
println(content)
} finally {
source.close() // 必须关闭资源,避免内存泄漏
}
// 方式2:使用 scala.util.Using(Scala 2.13+ 推荐,自动关闭资源)
import scala.util.Using
Using(Source.fromFile(filePath, "UTF-8")) { source =>
val content = source.mkString
println("\nUsing 读取的内容:")
println(content)
}.recover { // 处理异常
case e: Exception => println(s"读取文件失败:${e.getMessage}")
}
}
}
2. 按行读取文件
scala
dart
import scala.io.Source
import scala.util.Using
object FileReadByLineDemo {
def main(args: Array[String]): Unit = {
val filePath = "test.txt"
// 方式1:获取行迭代器(逐行处理)
Using(Source.fromFile(filePath)) { source =>
val lines: Iterator[String] = source.getLines()
lines.zipWithIndex.foreach { case (line, index) =>
println(s"第 ${index + 1} 行:$line")
}
}.recover {
case e: Exception => println(s"读取失败:${e.getMessage}")
}
// 方式2:将行转为列表/数组
Using(Source.fromFile(filePath)) { source =>
val lineList: List[String] = source.getLines().toList
val lineArray: Array[String] = source.getLines().toArray // 注意:迭代器只能遍历一次
println(s"\n文件共有 ${lineList.size} 行")
}
}
}
3. 读取二进制文件
scala.io.Source 主要用于文本文件,二进制文件建议使用 Java 的 FileInputStream:
scala
ini
import java.io.{File, FileInputStream}
import scala.util.Using
object BinaryFileReadDemo {
def main(args: Array[String]): Unit = {
val filePath = "test.bin"
Using(new FileInputStream(new File(filePath))) { in =>
val buffer = new Array[Byte](1024)
var len = 0
while ({len = in.read(buffer); len != -1}) {
// 处理二进制数据(如写入输出流、解析字节等)
println(s"读取到 ${len} 字节")
}
}.recover {
case e: Exception => println(s"读取二进制文件失败:${e.getMessage}")
}
}
}
二、文件写入
Scala 标准库中没有专门的写入工具,通常使用Java IO (PrintWriter、FileWriter、BufferedWriter)或 Scala 的 scala.tools.nsc.io.File(需引入依赖)。
1. 使用 Java PrintWriter 写入(覆盖 / 追加)
scala
typescript
import java.io.PrintWriter
import scala.util.Using
object FileWriteDemo {
def main(args: Array[String]): Unit = {
val filePath = "output.txt"
// 方式1:覆盖写入(默认)
Using(new PrintWriter(filePath)) { writer =>
writer.println("Hello, Scala!") // 写入一行,自动换行
writer.print("文件写入测试") // 写入内容,不换行
writer.flush() // 刷新缓冲区
}.recover {
case e: Exception => println(s"写入失败:${e.getMessage}")
}
// 方式2:追加写入(结合 FileWriter)
import java.io.FileWriter
Using(new PrintWriter(new FileWriter(filePath, true))) { writer =>
writer.println("\n这是追加的内容")
}
}
}
2. 使用 Java BufferedWriter 批量写入(高效)
scala
ini
import java.io.{BufferedWriter, FileWriter}
import scala.util.Using
object BufferedWriteDemo {
def main(args: Array[String]): Unit = {
val filePath = "batch_output.txt"
val lines = List("第一行内容", "第二行内容", "第三行内容")
// 缓冲写入,适合大量数据
Using(new BufferedWriter(new FileWriter(filePath))) { writer =>
lines.foreach { line =>
writer.write(line)
writer.newLine() // 换行(跨平台兼容)
}
}.recover {
case e: Exception => println(s"批量写入失败:${e.getMessage}")
}
}
}
3. 使用 Scala scala.tools.nsc.io.File 写入(需依赖)
scala
arduino
// 需在 build.sbt 中添加依赖:libraryDependencies += scalaOrganization.value % "scala-compiler" % scalaVersion.value
import scala.tools.nsc.io.File
object ScalaFileWriteDemo {
def main(args: Array[String]): Unit = {
val file = File("scala_output.txt")
// 覆盖写入
file.writeAll("Scala 原生文件操作\n", "第二行内容")
// 追加写入
file.appendAll("\n追加的内容")
// 按行写入
file.writeLines(List("行1", "行2", "行3"))
}
}
三、大文件处理(流式读取 / 写入)
对于大文件(GB 级),直接读取整个文件会导致内存溢出,需使用流式处理(逐行读取 / 写入),或借助第三方库:
scala
ini
import scala.io.Source
import java.io.PrintWriter
import scala.util.Using
object BigFileProcessDemo {
def main(args: Array[String]): Unit = {
val inputPath = "big_input.txt"
val outputPath = "big_output.txt"
// 流式读取大文件,逐行处理并写入
Using(Source.fromFile(inputPath)) { source =>
Using(new PrintWriter(outputPath)) { writer =>
source.getLines().foreach { line =>
// 处理每行数据(如过滤、转换)
val processedLine = line.toUpperCase() // 示例:转为大写
writer.println(processedLine)
}
}
}.recover {
case e: Exception => println(s"大文件处理失败:${e.getMessage}")
}
}
}
四、关键注意事项
- 资源关闭 :Scala 2.13+ 推荐使用
scala.util.Using自动关闭资源(替代手动finally),避免资源泄漏。 - 编码问题 :读取 / 写入文件时显式指定编码(如
UTF-8),避免中文乱码。 - 异常处理 :文件操作可能抛出
FileNotFoundException、IOException等,需通过recover或try-catch处理。 - 大文件 :避免使用
mkString或toList一次性读取整个文件,采用逐行流式处理。
五、第三方库推荐
- Akka Stream:适用于异步、流式的文件处理(高并发场景)。
- FS2:纯函数式的流式处理库,支持文件读写、并发控制。
- Better Files :简化的 Scala 文件操作库(
com.github.pathikrit%better-files%3.9.2)。