读取文件

43 阅读1分钟

image.png

object score01 {
  case class Stu(name:String, yuwen:Double, shuxue:Double, yingyu:Double)

  def main(args: Array[String]): Unit = {
    // 0. 创建一个可变list
    val stulist = scala.collection.mutable.ListBuffer[Stu]()

    // 1. 读入文件 迭代器
    val lines = scala.io.Source.fromFile("score.txt").getLines()

    lines.next() // 跳过第一行

    while(lines.hasNext){
      val line = lines.next()
      // 字符串拆分
      val li = line.split(":")
      stulist += Stu(li(0), li(1).toDouble, li(2).toDouble, li(3).toDouble)
    }
    // 读入数据结束
    println("读入数据结束")

    stulist.foreach(stu => {
      val total = stu.yuwen + stu.yingyu + stu.shuxue
      val avg = total / 3
      println(s"${stu.name}, 总分: $total, 平均分: $avg")
    })
  }
}

一、整体结构与核心知识点

代码用到了 Scala 的「样例类(case class)」「可变集合(ListBuffer)」「文件 IO」「循环遍历」等核心特性,流程分为:定义数据结构 → 读取文件 → 解析数据 → 计算成绩 → 输出结果。

二、逐行代码解释

scala

object score01 {  // 定义一个单例对象(Scala 程序入口必须是 object)
  // 1. 定义样例类:封装学生成绩数据(相当于轻量级的实体类)
  case class Stu(name:String, yuwen:Double, shuxue:Double, yingyu:Double)
  // 样例类特性:自动生成构造器、toString、equals 等方法,适合封装简单数据
  // 参数说明:name=姓名,yuwen=语文成绩,shuxue=数学成绩,yingyu=英语成绩(Double 支持小数)

  def main(args: Array[String]): Unit = {  // 程序入口方法(main 方法)
    // 2. 创建可变ListBuffer:存储多个学生的成绩对象(可变集合,支持动态添加元素)
    val stulist = scala.collection.mutable.ListBuffer[Stu]()

    // 3. 读取文件:获取文件的行迭代器(按行读取 score.txt)
    val lines = scala.io.Source.fromFile("score.txt").getLines()
    // Source.fromFile("score.txt"):打开 score.txt 文件(需确保文件在项目根目录)
    // getLines():返回文件行的迭代器(一行一行读取,不一次性加载全部内容,省内存)

    // 4. 跳过文件第一行(通常是表头,比如“姓名:语文:数学:英语”,不需要解析)
    lines.next() 

    // 5. 循环读取文件每一行(解析数据并封装到 ListBuffer)
    while(lines.hasNext){  // hasNext:判断迭代器是否还有下一行数据
      val line = lines.next()  // 取出当前行的字符串(比如:"小红:98:82:93")
      val li = line.split(":")  // 按冒号拆分字符串,得到数组(li(0)=姓名,li(1)=语文,依此类推)
      // 将拆分后的数据封装为 Stu 对象,添加到 ListBuffer
      stulist += Stu(li(0), li(1).toDouble, li(2).toDouble, li(3).toDouble)
      // toDouble:将字符串类型的成绩转为 Double 类型(比如 "98" → 98.0)
    }
    println("读入数据结束")  // 提示数据读取完成

    // 6. 遍历学生列表,计算并输出总分、平均分
    stulist.foreach(stu => {  // 遍历 ListBuffer 中的每个 Stu 对象(stu 是单个学生的对象)
      val total = stu.yuwen + stu.yingyu + stu.shuxue  // 计算总分:语文+英语+数学
      val avg = total / 3  // 计算平均分:总分 ÷ 3
      // 格式化输出:${} 是 Scala 字符串插值,直接嵌入变量值
      println(s"${stu.name}, 总分: $total, 平均分: $avg")
    })
  }
}

三、关键细节补充

  1. 文件格式要求score.txt 必须是「冒号分隔」的格式,示例:

    plaintext

    姓名:语文:数学:英语  // 第一行表头(会被 lines.next() 跳过)
    小红:98:82:93
    小明:90:85:95
    小刚:98:83:79
    
  2. 核心类 / 方法的作用

    • case class Stu:替代 Java 的 POJO 类,极简封装数据;
    • ListBuffer:可变列表(Scala 默认 List 不可变,ListBuffer 支持动态添加);
    • Source.fromFile:Scala 内置的文件读取工具;
    • foreach:函数式遍历(替代 for 循环,更简洁);
    • 字符串插值 s"${}":直接拼接变量,比 Java 的 + 号更优雅。
  3. 执行结果示例运行代码后控制台会输出:

    plaintext

    读入数据结束
    小红, 总分: 273.0, 平均分: 91.0
    小明, 总分: 270.0, 平均分: 90.0
    小刚, 总分: 260.0, 平均分: 86.66666666666667
    

四、潜在注意点

  • 如果 score.txt 文件不存在,会抛出「文件未找到」异常;
  • 如果成绩不是数字(比如输入了字母),toDouble 会抛出类型转换异常;
  • 如果行数据拆分后不足 4 个元素(比如少一个成绩),会抛出数组下标越界异常。