文件读写-成绩分析

在 Scala 中进行文件读写,主要有两种常用方式:一是利用 Scala 标准库中封装的 Java IO 操作 (如 java.io.FileBufferedReaderPrintWriter 等),二是使用 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 IOPrintWriterFileWriterBufferedWriter)或 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}")
    }
  }
}

四、关键注意事项

  1. 资源关闭 :Scala 2.13+ 推荐使用 scala.util.Using 自动关闭资源(替代手动 finally),避免资源泄漏。
  2. 编码问题 :读取 / 写入文件时显式指定编码(如 UTF-8),避免中文乱码。
  3. 异常处理 :文件操作可能抛出 FileNotFoundExceptionIOException 等,需通过 recovertry-catch 处理。
  4. 大文件 :避免使用 mkStringtoList 一次性读取整个文件,采用逐行流式处理。

五、第三方库推荐

  • Akka Stream:适用于异步、流式的文件处理(高并发场景)。
  • FS2:纯函数式的流式处理库,支持文件读写、并发控制。
  • Better Files :简化的 Scala 文件操作库(com.github.pathikrit % better-files % 3.9.2)。
相关推荐
小冻梨1 天前
模式匹配-基础使用
scala
顧棟4 天前
JAVA、SCALA 与尾递归
java·开发语言·scala
深兰科技4 天前
坦桑尼亚与新加坡代表团到访深兰科技,促进AI在多领域的应用落地
java·人工智能·typescript·scala·perl·ai大模型·深兰科技
a程序小傲5 天前
scala中的Array
开发语言·后端·scala
kk哥88995 天前
scala 介绍
开发语言·后端·scala
17316 天前
scala中的Array
scala
满山狗尾草7 天前
map的常规操作
scala
渣渣盟8 天前
Flink实时数据写入Redis实战
大数据·scala·apache
pale_moonlight8 天前
十、Scala应用实践(下)
linux·开发语言·scala