文件读写-成绩分析

在 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)。
相关推荐
是阿威啊3 天前
【用户行为归因分析项目】- 【企业级项目开发第四站】模拟三类用户行为数据上传到Hadoop
大数据·hadoop·分布式·sql·scala
今天没有盐5 天前
Python字符串操作全解析:从基础定义到高级格式化
后端·scala·编程语言
是阿威啊6 天前
【用户行为归因分析项目】- 【企业级项目开发第一站】项目架构和需求设计
大数据·hive·hadoop·架构·spark·scala
代码于老总8 天前
【Scala 技巧】用隐式类给 String “开挂”:一行代码实现手机号 / 身份证号校验
scala
scala舔狗汪8 天前
scala的隐式对象和隐式类
scala
是阿威啊9 天前
【maap-analysis】spark离线数仓项目完整的开发流程
大数据·分布式·spark·scala
豚踢兔x14 天前
正则表达式应用-手机号打码
scala
代码于老总15 天前
正则表达式在 Scala 中的应用
scala
凯新生物21 天前
聚乙二醇二生物素,Biotin-PEG-Biotin在生物检测中的应用
scala·bash·laravel·perl