object words01 {
def main(args: Array[String]): Unit = {
// 1. 读取文件内容
val content = scala.io.Source.fromFile("test.txt").mkString
// 2. 把字符串拆分为单词
// 使用正则表达式 \\W+ 去拆分字符串,\\W 表示非单词字符(!, ., 空格等)
val wordList = content.split("\\W+")
.map(_.toLowerCase()) // 转换为小写
.filter(_.nonEmpty) // 过滤空字符串
// 3. 统计每个单词出现的次数
val map1 = scala.collection.mutable.Map[String, Int]()
// 对于每个单词进行统计
wordList.foreach(word => {
if (map1.contains(word)) {
map1(word) += 1 // 存在:把它的值+1
} else {
map1(word) = 1 // 不存在:把它的值设为1
}
})
// 4. 对结果排序(降序排列)
// Map本身是无序的,把它转换成List进行排序
val sortedWordList = map1.toList
.sortBy(_._2) // 根据元组的第二个值(词频)排序
.reverse // 翻转,变为降序
// 5. 打印结果
sortedWordList.foreach(e1 => println(e1))
}
}
Scala 文件读写与单词统计概要
一、文件读取
1. 基本文件读取方法
scala
import scala.io.Source
// 1. 读取整个文件为字符串
val content: String = Source.fromFile("test.txt").mkString
// 2. 逐行读取
val lines: Iterator[String] = Source.fromFile("test.txt").getLines()
val lineList: List[String] = lines.toList
// 3. 读取为字符数组
val chars: Array[Char] = Source.fromFile("test.txt").toArray
2. 带编码的文件读取
scala
// 指定编码格式
Source.fromFile("test.txt", "UTF-8").mkString
3. 资源安全读取(自动关闭)
scala
import scala.util.Using
Using.resource(Source.fromFile("test.txt")) { source =>
source.mkString
}
二、文件写入
1. 使用 java.io 包
scala
import java.io.{PrintWriter, File}
// 1. 基本写入
val writer = new PrintWriter(new File("output.txt"))
writer.write("Hello, World!")
writer.close()
// 2. 使用 try-finally 确保关闭
val writer2 = new PrintWriter(new File("output.txt"))
try {
writer2.write("Content")
} finally {
writer2.close()
}
2. 使用 Scala 工具类
scala
import scala.sys.process._
// 将字符串写入文件
"Hello World" #> new java.io.File("output.txt") !
三、单词统计完整流程
1. 基本流程代码
scala
object WordCount {
def main(args: Array[String]): Unit = {
// 1. 读取文件
val content = scala.io.Source.fromFile("test.txt").mkString
// 2. 清洗和分割单词
val words = content.toLowerCase() // 转为小写
.replaceAll("[^a-zA-Z0-9\s]", " ") // 替换标点为空格
.split("\s+") // 按空白字符分割
.filter(_.nonEmpty) // 过滤空字符串
// 3. 统计词频(多种方式)
// 方式1:使用可变Map(传统命令式)
val map1 = scala.collection.mutable.Map[String, Int]()
words.foreach { word =>
map1(word) = map1.getOrElse(word, 0) + 1
}
// 方式2:使用不可变Map(函数式)
val map2 = words.groupBy(identity) // 按单词分组
.mapValues(_.length) // 统计每组数量
// 方式3:使用foldLeft
val map3 = words.foldLeft(Map[String, Int]()) { (acc, word) =>
acc + (word -> (acc.getOrElse(word, 0) + 1))
}
// 4. 排序输出
val sorted = map2.toList
.sortBy(-_._2) // 按词频降序
.take(10) // 取前10个
// 5. 输出结果
println("Top 10 words:")
sorted.foreach { case (word, count) =>
println(s"$word: $count")
}
// 6. 写入文件
val writer = new java.io.PrintWriter("result.txt")
sorted.foreach { case (word, count) =>
writer.println(s"$word\t$count")
}
writer.close()
}
}
2. 优化版本(模块化设计)
scala
object AdvancedWordCount {
// 读取文件
def readFile(filename: String): String = {
scala.io.Source.fromFile(filename).mkString
}
// 清洗文本
def cleanText(text: String): String = {
text.toLowerCase()
.replaceAll("[^a-zA-Z0-9\s]", " ")
.replaceAll("\s+", " ")
}
// 分割单词
def splitWords(text: String): Array[String] = {
text.split("\s+").filter(_.nonEmpty)
}
// 统计词频
def countWords(words: Array[String]): Map[String, Int] = {
words.groupBy(identity).mapValues(_.length)
}
// 排序结果
def sortResults(wordCounts: Map[String, Int]): List[(String, Int)] = {
wordCounts.toList.sortBy(-_._2)
}
// 写入结果
def writeResults(results: List[(String, Int)], filename: String): Unit = {
val writer = new java.io.PrintWriter(filename)
results.foreach { case (word, count) =>
writer.println(f"$word%-15s $count%d")
}
writer.close()
}
def main(args: Array[String]): Unit = {
// 执行流程
val content = readFile("test.txt")
val cleaned = cleanText(content)
val words = splitWords(cleaned)
val counts = countWords(words)
val sorted = sortResults(counts)
// 输出到控制台
sorted.take(20).foreach(println)
// 保存到文件
writeResults(sorted, "wordcount_result.txt")
}
}
四、实用技巧
1. 处理大文件
scala
// 流式处理,避免内存溢出
val wordCounts = scala.io.Source.fromFile("large.txt")
.getLines()
.flatMap(line => line.toLowerCase().split("\W+"))
.filter(_.nonEmpty)
.foldLeft(Map[String, Int]()) { (map, word) =>
map + (word -> (map.getOrElse(word, 0) + 1))
}
2. 忽略停用词
scala
val stopWords = Set("the", "a", "an", "and", "or", "but", "in", "on", "at")
val filteredCounts = wordCounts.filterNot {
case (word, _) => stopWords.contains(word)
}
3. 多文件统计
scala
val files = List("file1.txt", "file2.txt", "file3.txt")
val totalCounts = files.flatMap { file =>
scala.io.Source.fromFile(file)
.mkString
.split("\W+")
.map(_.toLowerCase)
.filter(_.nonEmpty)
}.groupBy(identity)
.mapValues(_.length)
五、Spark 版本(大数据处理)
scala
import org.apache.spark.{SparkConf, SparkContext}
object SparkWordCount {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("WordCount")
val sc = new SparkContext(conf)
// 读取文件
val textFile = sc.textFile("hdfs://path/to/largefile.txt")
// 单词统计
val counts = textFile.flatMap(line => line.split(" "))
.map(word => (word.toLowerCase(), 1))
.reduceByKey(_ + _)
// 保存结果
counts.saveAsTextFile("hdfs://path/to/output")
sc.stop()
}
}
六、总结要点
-
文件读取:优先使用
Source.fromFile,大文件使用流式处理 -
文本清洗:注意大小写转换和标点符号处理
-
统计方法:
- 小数据:使用
groupBy + mapValues - 大数据:使用
foldLeft或 Spark
- 小数据:使用
-
结果输出:注意排序和格式化
-
资源管理:确保文件读写后正确关闭