Scala学习笔记15: 文件和正则表达式

目录

    • [第十五章 文件和正则表达式](#第十五章 文件和正则表达式)
      • [1- 读取行](#1- 读取行)
      • [2- 从URL或者其它源读取](#2- 从URL或者其它源读取)
      • [3- 写入文本文件](#3- 写入文本文件)
      • [4- 序列化](#4- 序列化)
      • [5- 正则表达式](#5- 正则表达式)
      • [6- 正则表达式验证输入数据格式](#6- 正则表达式验证输入数据格式)
      • end

第十五章 文件和正则表达式

1- 读取行

在Scala中读取文件中的行可以通过不同的方法实现 ;

一种常见的方法是使用 scala.io.Source 对象来逐行读取文件内容 ;

示例 :

scala 复制代码
import scala.io.Source

object FileReadingLinesExample {

  def main(args: Array[String]): Unit = {
    val fileName = "src/main/resources/test.txt"

    try {
      val source = Source.fromFile(fileName)
      val lines = source.getLines().toList
      source.close()

      println("文中的行: ")
      lines.foreach(println)
    } catch {
      case e: Exception => println("文件读取错误: " + e.getMessage)
    }
  }
}
shell 复制代码
# 输出
文中的行: 
《登雀鹤楼》
唐.王之涣
白日依山尽,
黄河入海流。
欲穷千里目,
更上一层楼。

在这个示例中, 我首先导入了 scala.io.Source 类 ;

然后, 我们指定要读取的文件名, 并使用 Source.fromFile(fileName) 创建一个 Source 对象 ;

接着, 我们使用 getLines() 方法逐行读取文件内容, 并将每行存储在一个列表中 ;

最后, 我们关闭文件流并打印出读取的所有行 .

注意, 这只是一个简单的示例, 实际应用中可能需要更多的错误处理和资源管理 ;

确保文件存在并具有适当的读取权限 ;

你可以根据需要进一步扩展和优化这段代码 .

2- 从URL或者其它源读取

在Scala中, 你可以使用 scala.io.Source 类来从URL或其他来源读取文件内容 ;

示例 :

scala 复制代码
import scala.io.Source
import java.net.URL

object URLReadingExample {
  def main(args: Array[String]): Unit = {
    val url = new URL("https://raw.githubusercontent.com/dpx0110/files/main/poem.txt")
    try {
      val source = Source.fromURL(url)
      val content = source.mkString
      source.close()

      println("从URL读取的文件内容: ")
      println(content)
    } catch {
      case e: Exception => println(s"Error reading URL: ${e.getMessage}")
    }
  }
}
  • 在这个示例中, 我们导入了 scala.io.Source 类和 java.net.URL 类 ;
  • 然后, 我们创建一个 URL 对象, 指定要读取的URL地址 ;
  • 接着, 我们使用Source.fromURL(url) 方法从URL读取文件内容, 并将其存储为字符串 ;
  • 最后, 我们关闭文件流并打印出读取的内容 .
scala 复制代码
// 其它源读取
val source1 = Source.fromString("hello world! ")
val source2 = Source.stdin
...

请确保URL地址有效并具有适当的访问权限 ;

根据实际情况修改URL地址, 以适应你的文件读取需求 ;

这段代码可以帮助你从URL或其他来源读取文件内容 .

3- 写入文本文件

在Scala中写入文本文件, 可以使用多种方法, 一下是几种常见方式 :

**1. 使用 java.io.PrintWriter **

这是最直接的方式, 利用 Java 的 PrintWriter 类写入数据到文件 ;

scala 复制代码
import java.io.PrintWriter

object WriteToFile {
  def main(args: Array[String]): Unit = {
    val filePath = "src/main/resources/poem1.txt"
    val writer = new PrintWriter(filePath)

    try {
      writer.println("《题西林壁》")
      writer.println("宋.苏轼")
      writer.println("横看成岭侧成峰,")
      writer.println("远近高低各不同。")
      writer.println("不识庐山真面目,")
      writer.println("只缘身在此山中。")
    } finally {
      writer.close()
    }
  }
}
shell 复制代码
《题西林壁》
宋.苏轼
横看成岭侧成峰,
远近高低各不同。
不识庐山真面目,
只缘身在此山中。

2. 使用 java.io.FileWriterjava.io.BufferedWriter

这种方式更注重效率, BufferedWriter 可以提高写入效率, 尤其在处理大量数据时 ;

scala 复制代码
import java.io.{BufferedWriter, FileWriter}

object WriteToFile {
  def main(args: Array[String]): Unit = {
    val filePath = "src/main/resources/poem2.txt"
    val writer = new FileWriter(filePath)
    val bufferedWriter = new BufferedWriter(writer)

    try {
      bufferedWriter.write("《题西林壁》\n") // 须手动添加换行符
      bufferedWriter.write("宋.苏轼\n")
      bufferedWriter.write("横看成岭侧成峰,\n")
      bufferedWriter.write("远近高低各不同。\n")
      bufferedWriter.write("不识庐山真面目,\n")
      bufferedWriter.write("只缘身在此山中。\n")
    } finally {
      bufferedWriter.close()
    }
  }
}
shell 复制代码
《题西林壁》
宋.苏轼
横看成岭侧成峰,
远近高低各不同。
不识庐山真面目,
只缘身在此山中。

4- 序列化

在分布式系统、大数据处理以及需要将对象状态保存到磁盘的场景中, 序列化扮演着至关重要的角色 ;

Scala作为一门运行于Java虚拟机上的语言, 自然也需要处理对象的序列化和反序列化问题 ;

Scala本身没有提供原生的序列化机制, 而是依赖于Java的序列化机制或第三方库来实现 ;

1. 使用Java序列化

最直接的方式是使用Java自带的序列化机制 ;

你只需要让你的类继承 java.io.Serializzble 接口 , 并添加 serialVersionUID 即可 ;

scala 复制代码
    // 序列化 和 反序列化
    import java.io._

    @SerialVersionUID(100L)
    class Person(val name: String, val age: Int) extends Serializable {
      override def toString: String = s"Person(name=$name, age=$age)"
    }

    // 序列化
    val person = new Person("Tom", 18)
    val outputStream = new FileOutputStream("person.ser")
    val objectOutputStream = new ObjectOutputStream(outputStream)
    objectOutputStream.writeObject(person)
    objectOutputStream.close()

    // 反序列化
    val inputStream = new FileInputStream("person.ser")
    val objectInputStream = new ObjectInputStream(inputStream)
    val loadedPerson = objectInputStream.readObject().asInstanceOf[Person]
    objectInputStream.close()

    println(loadedPerson) // Output: Person(name=Tom, age=18)
    println(loadedPerson.getClass) // Output: class org.puture.scala.MyFiles$Person$1
    println(loadedPerson.name) // Output: Tom
    println(loadedPerson.age) // Output: 18
  • 优点: 简单直接, 开箱即用
  • 缺点:
    • 只能序列化实现了 java.io.Serializable 接口的类
    • 序列化后的数据格式与Java绑定, 不够灵活
    • 性能相对较低

2. 使用第三方库

为了克服Java序列化的缺点, Scala社区涌现出许多优秀的第三方序列化库, 例如:

  • Json库:
    • uPickle: 专注于速度和简洁性, 使用宏生成高效的序列化代码 ;
    • Circe: 类型安全, 功能强大, 支持多种数据格式 ;
    • Play Json: Play框架的一部分, 易于使用, 适用于Web应用程序 ;
  • 其他库:
    • Kryo: 高性能序列化库, 适用于需要极致速度的场景 ;
    • Chill: Twitter开发的序列化库, 支持多种数据格式, 包括Kryo和Json .

选择合适的序列化方式

选择哪种序列化方式取决于你的具体要求 :

  • 简单项目: 如果你的项目比较简单, 对性能要求不高, 可以使用Java序列化或者uPickle ;
  • **Web应用程序: ** 可以考虑使用Play Json, 它与Play框架集成良好 ;
  • **高性能需求: ** 如果你的项目对性能要求很高, 可以考虑使用Kryo或者Chill ;
  • **类型安全: ** 如果需要类型安全的序列化, 建议使用 Circe等库 ;

总而言之, Scala提供了多种方式类处理对象的序列化和反序列化, 你需要根据项目的具体情况选择合适的方式 .

5- 正则表达式

Scala中的正则表达式使用与 Java相同的语法, 但它提供了更简洁、更强大的方式来匹配和操作文本 ;

1. 基本语法

Scala中的正则表达式使用 r 字符串字面量来定义 ; 例如 :

scala 复制代码
val regex = "hello".r

这个正则表达式将匹配字符串 "hello" ;

2. 常用元字符

  • . : 匹配任意单个字符 ;
  • * : 匹配前面的字符零次或多次 ;
  • + : 匹配前面的字符一次或多次 ;
  • ? : 匹配前面的字符零次或一次 ;
  • | : 匹配左边或右边的表达式 ;
  • [] : 匹配方括号内的任意字符 ;
  • [^...] : 匹配不在方括号内的任意字符 ;
  • \d : 匹配数字 ;
  • \s : 匹配空白字符 ;
  • \w : 匹配字母、数字或才划线 ;
  • \b : 匹配单词边界 ;
  • ^ : 匹配字符串开头 ;
  • $ : 匹配字符串结尾 ;

3. 匹配文本

可以使用 findAllIn 方法来查找匹配的文本 ;

scala 复制代码
    val text = "Hello, world!"
    val regex = "Hello".r
    val matches = regex.findAllIn(text)

    matches.foreach(println) // 输出: Hello	

4. 替换文本

可以使用 replaceAllIn 方法来替换匹配的文本 ;

scala 复制代码
    val text = "Hello, world!"
    val regex = "world".r
    val replaced = regex.replaceAllIn(text, "Scala")

    println(replaced) // Output: Hello, Scala!

5. 分组

可以使用 () 来分组正则表达式, 并通过 group 方法获取匹配的子字符串 ;

scala 复制代码
    val text = "The quick brown fox jumps over the lazy dog."
    val regex = "(.+) (.+) (.+)".r

    val matches = regex.findAllMatchIn(text)

    matches.foreach(m => {
      println("Group 1: " + m.group(1)) // Group 1: The quick brown fox jumps over the
      println("Group 2: " + m.group(2)) // Group 2: lazy
      println("Group 3: " + m.group(3)) // Group 3: dog.
    })

6. 捕获组

可以使用 find 方法来查找第一个匹配的文本, 并使用 group 方法获取捕获组的内容 ;

scala 复制代码
    val text = "The quick brown fox jumps over the lazy dog."
    val regex = "(\\w+) (\\w+)".r
    val matches = regex.findPrefixOf(text)

    println(matches) // Output: Some(The quick)

    if (matches.isDefined) {
      val m = matches.get
      println(m) // Output: The quick
    }

7. 注意事项

  • 正则表达式语法较为复杂, 需要仔细理解才能灵活运用 ;
  • 正则表达式匹配效率可能较低, 特别是复杂的表达式, 需要谨慎使用 ;
  • Scala 中的正则表达式支持Java的正则表达式语法, 可以参考Java文档了解更多细节 ;

总结

Scala中的正则表达式功能强大, 能够满足各种文本匹配和处理的需求 ;

希望以上介绍能够帮助你更好的理解Scala中的正则表达式 .

6- 正则表达式验证输入数据格式

在Scala中, 你可以使用正则表达式来验证输入数据的格式, 例如邮箱地址、手机号等 ;

1. 准备工作

首先, 需要定义一个正则表达式, 用来匹配目标格式的数据 ;

例如:

  • 邮箱地址: ^.+@.+\\..+$
  • 手机号: ^1[3-9]\\d{9}$

2. 代码示例

scala 复制代码
object DataValidation {
  def main(args: Array[String]): Unit = {
    val emailRegex = "^.+@.+\\..+$".r
    val phoneRegex = "^1[3-9]\\d{9}$".r

    // 键盘输入
    println("请输入邮箱地址:")
    val email = scala.io.StdIn.readLine()
    println("请输入手机号:")
    val phone = scala.io.StdIn.readLine()

    // 验证邮箱地址
    if (emailRegex.findFirstIn(email).isDefined) {
      println("邮箱地址格式正确")
    } else {
      println("邮箱地址格式错误")
    }

    // 验证手机号
    if (phoneRegex.findFirstIn(phone).isDefined) {
      println("手机号格式正确")
    } else {
      println("手机号格式错误")
    }
  }
}
shell 复制代码
请输入邮箱地址:
6666@gmail.com
请输入手机号:
16688889999
邮箱地址格式正确
手机号格式正确

Process finished with exit code 0

请输入邮箱地址:
123.34@gamil.com
请输入手机号:
166888899996
邮箱地址格式正确
手机号格式错误

Process finished with exit code 0

3. 解释

  • Regex 类是Scala用于表示正则表达式的类 ;
  • findFirstIn 方法用于查找字符串中第一个匹配正则表达式的字符串, 如果找到则返回 Some(匹配的自字符串) , 否则返回 None ;
  • isDefined 方法用于判断 Option 类型的值是否为空 ;

4. 其它验证方法

除了使用 findFirstIn 方法, 还可以使用以下方法来验证数据格式 :

  • matches 方法: 判断整个字符串是否匹配正则表达式 ;
  • replaceAllIn 方法: 将字符串中所有匹配正则表达式的部分替换成其他字符串 ;

5. 注意事项

  • 正则表达式语法比较复杂, 需要仔细学习和理解 ;
  • 使用正则表达式进行数据格式验证只能保证数据符合预期的格式, 无法保证数据的有效性 ;
  • 例如: 验证有序地址格式, 并不能保证这个邮箱地址真实存在 ;

6. 扩展

除了验证邮箱地址和手机号, 还可以使用正则表达式来验证其他格式的数据, 例如:

  • 日期格式
  • 身份证号码
  • 邮政编码
  • URL地址
  • ...

end

相关推荐
Lingoesforstudy27 分钟前
c#中的超时终止
开发语言·笔记·c#
Yima_Dangxian36 分钟前
爬虫笔记20——票星球抢票脚本的实现
笔记·爬虫·python
nnerddboy1 小时前
PyQt5开发笔记:2. 2D与3D散点图、水平布局和边框修饰
笔记
2的n次方_1 小时前
迎接AI新时代:GPT-5即将登场的巨大变革与应用前瞻
人工智能·gpt·学习
xiandong201 小时前
240707_昇思学习打卡-Day19-基于MindSpore通过GPT实现情感分类
人工智能·gpt·学习·分类
观鉴词recommend1 小时前
【c++刷题笔记-动态规划】day32: 509. 斐波那契数 、 70. 爬楼梯 、 746. 使用最小花费爬楼梯
c++·笔记·算法·leetcode·动态规划
whatever who cares2 小时前
macOS笔记
笔记·macos
m0_689618282 小时前
生物墨水:3D组织生物打印的基石
人工智能·笔记
Tassel_YUE2 小时前
linux修改内核实现禁止被ping
linux·运维·笔记
sealaugh323 小时前
spring boot(学习笔记第十二课)
spring boot·笔记·学习