object class7 {
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("读入数据结束")
// 2. 计算
println("计算结束,开始写入")
// 3. 保存结果
val fileWriter = new FileWriter("score_result.txt")
fileWriter.write("高三19班成绩单 \r")
stuList.foreach(stu => {
val total = stu.yuwen + stu.yingyu + stu.shuxue
val avg = total / 3
fileWriter.write(s"${stu.name}, 总分:${total}, 平均分:${avg} \r\n")
})
fileWriter.close()
}
}
一、核心流程梳理
整体流程:定义学生数据结构 → 读取 score.txt 成绩文件 → 解析数据并封装为学生对象 → 计算每位学生的总分/平均分 → 将结果写入 score_result.txt 文件
二、逐行代码解释
scala
object score01 { // Scala 程序入口(单例对象)
// 1. 定义样例类:封装学生成绩(姓名+三门科目分数)
case class Stu(name:String, yuwen:Double, shuxue:Double, yingyu:Double)
// 样例类优势:自动生成构造器、toString 等方法,无需手动写 getter/setter
def main(args: Array[String]): Unit = { // 程序主方法
// 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"):打开成绩文件(需确保文件在项目根目录)
// getLines():按行读取文件,返回迭代器(省内存,逐行处理)
// 4. 跳过文件第一行(表头,比如“姓名:语文:数学:英语”)
lines.next()
// 5. 循环解析每一行成绩数据
while(lines.hasNext){ // 判断迭代器是否还有未读取的行
val line = lines.next() // 取出当前行(格式:姓名:语文:数学:英语,如“小红:98:82:93”)
val li = line.split(":") // 按冒号拆分字符串,得到数组
// 将拆分后的数据封装为 Stu 对象,添加到 ListBuffer
stuList += Stu(li(0), li(1).toDouble, li(2).toDouble, li(3).toDouble)
// li(0)=姓名,li(1)=语文(转 Double 支持小数成绩),li(2)=数学,li(3)=英语
}
println("读入数据结束") // 提示数据读取完成
// 6. 计算前的提示(仅日志作用)
println("计算结束,开始写入")
// 7. 核心扩展:将结果写入新文件 score_result.txt
// 7.1 创建文件写入器,指定要写入的文件名称
val fileWriter = new FileWriter("score_result.txt")
// 7.2 写入文件标题(\r 是回车符,适配不同系统换行)
fileWriter.write("高三19班成绩单 \r")
// 7.3 遍历学生列表,计算并写入每位学生的成绩
stuList.foreach(stu => {
val total = stu.yuwen + stu.yingyu + stu.shuxue // 计算总分
val avg = total / 3 // 计算平均分
// 写入一行结果:姓名 + 总分 + 平均分(\r\n 是回车+换行,保证每行独立)
fileWriter.write(s"${stu.name}, 总分:${total}, 平均分:${avg} \r\n")
})
// 7.4 关闭文件写入器(必须!否则数据可能只存在缓存,未真正写入文件)
fileWriter.close()
}
}
三、关键细节补充
1. 文件操作核心知识点
| 代码片段 | 作用 | 注意事项 |
|---|---|---|
new FileWriter("score_result.txt") | 创建文件写入器,若文件不存在则自动创建;若已存在则覆盖原有内容 | 如需追加内容,改用 new FileWriter("score_result.txt", true) |
fileWriter.write(内容) | 将字符串写入文件(先存到内存缓存) | 单次写入不会立即刷到硬盘 |
fileWriter.close() | 关闭写入器,同时将缓存中的数据刷入硬盘 | 必须调用!否则文件可能为空或内容不完整 |
2. 输入 / 输出文件格式说明
-
输入文件(score.txt) 格式(冒号分隔,第一行是表头):
plaintext
姓名:语文:数学:英语 小红:98:82:93 小明:90:85:95 小刚:98:83:79 -
输出文件(score_result.txt) 生成后的内容示例:
plaintext
高三19班成绩单 小红, 总分:273.0, 平均分:91.0 小明, 总分:270.0, 平均分:90.0 小刚, 总分:260.0, 平均分:86.66666666666667
3. 潜在问题(也是优化点)
这段代码缺少异常处理,实际运行中可能出现报错:
- 如果
score.txt不存在 → 抛出「文件未找到」异常; - 如果成绩数据格式错误(比如非数字)→
toDouble抛出类型转换异常; - 如果写入文件时权限不足 → 抛出 IO 异常;
- 未使用
try-finally确保fileWriter.close()执行(比如报错时可能跳过关闭操作)。