文件读写-成绩分析

在 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)。
相关推荐
Thomas21433 天前
Java scala 数组 链表
java·链表·scala
江畔柳前堤5 天前
消息队列:从直觉到精通的完整认知地图
开发语言·人工智能·算法·机器学习·ruby on rails·scala
hopsky19 天前
《Scala 学习手册》核心内容详解
人工智能·学习·scala
abcy0712131 个月前
scala playframework 搭建与新建controller教程
scala
lpfasd1231 个月前
编程语言榜单变迁分析
开发语言·后端·scala
戮漠summer2 个月前
Missing Semester 计算机教育中缺失的一课 Lecture 01 Shell
开发语言·后端·scala
醉熏的石头2 个月前
Ubuntu 中的编程语言(中)
linux·ubuntu·scala
Irene19912 个月前
Scala、Java、Python、JavaScript 的核心特性和应用场景(Python 的“单机“局限性:GIL 机制导致的多核并行缺陷)
java·javascript·python·scala
李白的天不白3 个月前
确认 Nginx 配置文件是否真的生效
scala
醉颜凉3 个月前
Scala自定义Monad实战:从理论到应用的完整指南
大数据·算法·scala