文件读写-全文单词统计

56 阅读2分钟

一、核心知识点梳理

1. 文件读写

  • 读取:用 scala.io.Source 按行读取,核心语法:

    scala

    import scala.io.Source
    // 读取文件(指定UTF-8避免中文乱码)
    val lines = Source.fromFile("data.txt", "UTF-8").getLines() // 返回每行迭代器
    
  • 写入:用 java.io.PrintWriter,必须关闭流保证写入成功:

    scala

    import java.io.{File, PrintWriter}
    val writer = new PrintWriter(new File("result.txt"))
    writer.println("写入内容") // 单行写入
    writer.close() // 关闭流(关键)
    

2. 字符串拆分

  • 核心语法:字符串.split("分隔符"),返回数组,搭配 trim() 去空格:

    scala

    val line = "李四 , 95"
    val parts = line.split(",").map(_.trim) // 拆分并去空格 → Array("李四", "95")
    val name = parts(0)
    val score = parts(1).toInt // 转为数字
    
  • 校验:避免无效行(如只有 1 个字段、分数非数字):

    scala

    if (parts.length == 2 && parts(1).forall(_.isDigit)) { /* 有效行处理 */ }
    

3. Map 排序

  • Map 本身无序,需转 List 后排序,核心两种方式:

    scala

    val scoreMap: Map[String, Int] = Map("张三"->85, "李四"->95, "王五"->85)
    
    // 方式1:sortBy(推荐)- 分数降序、姓名升序
    val sorted1 = scoreMap.toList.sortBy { case (name, score) => (-score, name) }
    
    // 方式2:sortWith(自定义)- 同上逻辑
    val sorted2 = scoreMap.toList.sortWith { 
      case ((n1, s1), (n2, s2)) => if (s1 != s2) s1 > s2 else n1 < n2 
    }
    

二、完整实战案例(可直接运行)

步骤 1:创建输入文件 data.txt

plaintext

张三,85
李四,92
王五,85
赵六,78
李四,95
钱七,90

步骤 2:完整代码

scala

import scala.io.Source
import java.io.{File, PrintWriter}

object ScalaFileMapDemo {
  def main(args: Array[String]): Unit = {
    // 1. 读取文件 + 字符串拆分 + 构建Map
    val scoreMap = Source.fromFile("data.txt", "UTF-8")
      .getLines() // 按行读取
      .filter(_.nonEmpty) // 过滤空行
      .map { line =>
        val parts = line.split(",").map(_.trim)
        // 校验格式,无效行直接抛出提示
        if (parts.length != 2 || !parts(1).forall(_.isDigit)) {
          throw new Exception(s"无效行:$line")
        }
        (parts(0), parts(1).toInt) // 转为(姓名,分数)元组
      }
      .toMap // 转Map(重复姓名会覆盖)

    // 2. Map排序:分数降序,分数相同则姓名升序
    val sortedScores = scoreMap.toList.sortBy { case (name, score) => (-score, name) }

    // 3. 写入排序结果到文件
    val writer = new PrintWriter(new File("sorted_result.txt"))
    try {
      writer.println("姓名,分数")
      sortedScores.foreach { case (name, score) =>
        writer.println(s"$name,$score")
      }
      println("处理完成!排序结果:")
      sortedScores.foreach { case (n, s) => println(s"$n: $s 分") }
    } finally {
      writer.close() // 确保流关闭
    }
  }
}

步骤 3:运行结果

  • 控制台输出:

    plaintext

    处理完成!排序结果:
    李四: 95 分
    钱七: 90 分
    张三: 85 分
    王五: 85 分
    赵六: 78 分
    
  • 输出文件 sorted_result.txt 内容:

    plaintext

    姓名,分数
    李四,95
    钱七,90
    张三,85
    王五,85
    赵六,78
    

三、关键注意事项

  1. 文件路径:若文件不在项目根目录,需写绝对路径(如 "/Users/xxx/data.txt");

  2. 异常处理:可加 try-catch 捕获文件不存在、格式错误等问题:

    scala

    try { /* 核心逻辑 */ } catch {
      case e: FileNotFoundException => println("文件没找到!")
      case e: Exception => println(s"错误:${e.getMessage}")
    }
    
  3. 大数据场景:用迭代器流式处理,避免一次性加载全部内容到内存;

  4. 排序扩展:若需按姓名降序,可改 sortBy 为 (-score, name)(Ordering.Tuple2(Ordering.Int, Ordering.String.reverse))