Scala入门到精通——第十二节 I/O与正则表达式

本节主要内容

  1. Scala I/O操作简介
  2. Scala 写文件
  3. Scala 读文件
  4. Scala 网络I/O
  5. 正则表达式简介
  6. Scala正则表达式实战

1. Scala I/O操作简介

I/O操作是一门编程语言中的重要内容,在Scala中,它更多的是调用java中的I/O类或者通过对java中的I/O类进行相应的封装来实现I/O操作。在上一节内容中我们已经用到了I/O操作:

trait FileLogger extends Logger{

  val fileName:String
  //PrintWriter使用的是java.io.PrintWriter类
  val fileOutput=new PrintWriter(fileName:String)
  fileOutput.println("#")

  def log(msg:String):Unit={
    fileOutput.print(msg)
    fileOutput.flush()
    }
}

scala自身关于I/O的内容比较少,下图给出的是scala I/O相关的类

可以看到,相比于java语言中的I/O类,scala语言中的I/O相关类数量就显得少得多,而这其中最常用的只有Source这个类,因此要学好scala I/O操作,必须对java中的I/O相关类有个比较深入的了解。

2. Scala 写文件

Scala进行文件写操作,直接用的都是java中的I/O类,例如

import java.io._

object ScalaFileWriter {
  def main(args: Array[String]): Unit = {
    val fileWriter=new FileWriter("file.txt")
    fileWriter.write("scala file writer")
    fileWriter.flush()
    fileWriter.close()
  }
}

可以看出 scala中的文件写操作与java中的I/O操作并没有什么区别,这说明了scala可以与java进行互操作。

3. 读文件

scala中读文件可以直接使用java中的I/O类,也可以用scala中的Source对象,该对象对java中的I/O进行了封装,使用更简便更灵活,下面的代码给出了如果读取文件并将文件内容格式化输出:

import scala.io._

object ScalaFileReader {
  def main(args: Array[String]): Unit = {
    //读取文件
    val file=Source.fromFile("D:\\scala\\doc\\api\\package.html")
    //返回Iterator[String]
    val lines=file.getLines()
    //打印内容
    for(i<- lines) println(i)
    //关闭文件
    file.close();
  }
}

4. 网络I/O

scala中的网络I/O操作可以通过Source对象中的fromURL方法来实现,也可以使用原生的JAVA 网络I/O操作进行,下面的代码演示的是scala中的网络I/O读取百度首页内容:

import java.net.{URL, URLEncoder}
import scala.io.Source.fromURL

object NetworkIO {
  def main(args: Array[String]): Unit = {
    print(fromURL(new URL("http://www.baidu.com")).mkString)
  }
}

5 正则表达式简介

在众多的编程语言当中,包括JAVA、Perl、PHP、Python、JavaScript和JScript,都无一例外内生地支持正则表达式处理。Scala语言同样支持正则表达式,当然,scala可以直接通过Java操作正则表达式的方式使用正则表达式,但scala实现了自己的方式,它更为灵活。值得一提的是正则表达式并不只属于某一门程序语言,它已经超出了某种语言或某个系统的局限,成为被人们广为使用的工具。

在程序开发中,经常会碰到需要匹配、查找、替换、判断字符串,如果用纯编码方式解决的话,难度较大,而且很浪费时间,通过正则表达式可以解决这些问题。下面给出正则表达式中常用符号的含义:

1 句点符号.,它是一种通配符,用于匹配一个字符,例如Spa.k,可以匹配Spark、Spaak等任意字母组成的字符串,还可以匹配Spa#k,Spa k等特殊字符组成的字符串

2 [],限定匹配,例如Spa[ark]k只会匹配Spark,Spaak,Spakk这三个字符串,对于其它的不会匹配

3 |, 或匹配,例如Spa(a|r|rr|k)k,则可以匹配Spark,Spaak,Spakk及Sparrk

4 $,匹配行结束符,例如Spark$ 匹配的是以Spark$ 为结尾行,例如I love Spark,但它不匹配Spark will be very poupular in the future

5 ^,匹配行开始符,例如^Spark匹配的是以Spark开始的行,如Spark will be very poupular in the future,不匹配I love Spark

6 *,匹配0至多个字符,例如Spar*,可以匹配任何Spar开始的字符串,如Spar,Spark,Sparkkkkk

7 /,转义符,例如Spark/$ 匹配的是包含Spark$的字符串

8 ( ),分组符,它会将()中匹配的内容保存起来,可以对其进行访问,例如Spa(a|r|rr|k)k可以对()中匹配的内容保存为一个临时变量,在程序中可以直接对其进行访问

9 +,匹配一次或多次例如Spar+,可以匹配任何Spar开始的字符串,如Spark,Sparkkkkk

10 ?,匹配0次或一次,例如Spark(s)? 可以匹配Spark和Sparks

11 {n},匹配n次,例如Spark{2},可以匹配I love Sparkk中的Sparkk

12 {n,},至少匹配n次,例如Spark{2,}可以匹配I love Sparksss Sparkss中的Sparksss和Sparkss

13 {n,m},至少匹配n次,最多匹配m次,Sparks{2,4}可以匹配I love Sparks Sparkssss中的Sparkssss

限定匹配[]的用法非常灵活,有必要对其进行进一步的说明:

[a-z]     条件限制在小写a to z范围中一个字符
[A-Z]     条件限制在大写A to Z范围中一个字符
[a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符
[0-9]     条件限制在小写0 to 9范围中一个字符
[0-9a-z] 条件限制在小写0 to 9或a to z范围中一个字符
[0-9[a-z]] 条件限制在小写0 to 9或a to z范围中一个字符(交集)
^符号在限定匹配[]中有另外的含义,即取反操作
[^a-z]     条件限制在非小写a to z范围中一个字符
[^A-Z]     条件限制在非大写A to Z范围中一个字符
[^a-zA-Z] 条件限制在非小写a to z或大写A to Z范围中一个字符
[^0-9]     条件限制在非小写0 to 9范围中一个字符
[^0-9a-z] 条件限制在非小写0 to 9或a to z范围中一个字符

其它特殊字符:

\ 反斜杠

\t 间隔 (‘/u0009’)

\n 换行 (‘/u000A’)

\r 回车 (‘/u000D’)

\d 数字 等价于[0-9]

\D 非数字 等价于[^0-9]

\s 空白符号 [/t/n/x0B/f/r]

\S 非空白符号 [^/t/n/x0B/f/r]

\w 单独字符 [a-zA-Z_0-9]

\W 非单独字符 [^a-zA-Z_0-9]

\f 换页符

\e Escape

\b 一个单词的边界

\B 一个非单词的边界

\G 前一个匹配的结束

6 常用正则表达式实战

下面给出最为常用的几种正则表达式的操作来领略正则表达式的魅力及它在scala中是如何使用的。

1 匹配邮箱:

object RegexMatch {
  def main(args: Array[String]): Unit = {
    val sparkRegex="^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$".r
    for(matchString <- sparkRegex.findAllIn("[email protected]"))
    {
      println(matchString)
    }
  }
}

2 匹配网址:

object RegexMatch {
  def main(args: Array[String]): Unit = {
    val sparkRegex="^[a-zA-Z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\s*)?$".r
    for(matchString <- sparkRegex.findAllIn("http://www.xuetuwuyou.com"))
    {
      println(matchString)
    }
  }
}

3 匹配手机号码:

object RegexMatch {
  def main(args: Array[String]): Unit = {
    val sparkRegex="(86)*0*13\\d{9}".r
    for(matchString <- sparkRegex.findAllIn("13887888888"))
    {
      println(matchString)
    }
  }
}

4 匹配IP地址:


object RegexMatch {
  def main(args: Array[String]): Unit = {
    val sparkRegex="(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)".r
    for(matchString <- sparkRegex.findAllIn("192.168.1.1"))
    {
      println(matchString)
    }
  }
}

在scala中,有一个非常非常强大的功能,那就是提取器(Extractor),在后面我们会专门拿一讲来讲解scala的提取器,本节只是简单演示一下提取器是如何与scala中的正则表达式一直使用的。

提取匹配的IP地址子段:

object RegexMatch {
  def main(args: Array[String]): Unit = {
    val ipRegex="(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)".r
    for(ipRegex(one,two,three,four) <- ipRegex.findAllIn("192.168.1.1"))
    {
      println("IP子段1:"+one)
      println("IP子段2:"+two)
      println("IP子段3:"+three)
      println("IP子段4:"+four)
    }
  }
}

提取邮箱中的用户名:

object RegexMatch {
  def main(args: Array[String]): Unit = {
    val sparkRegex="^([\\w-]+(\\.[\\w-]+)*)@[\\w-]+(\\.[\\w-]+)+$".r
    for(sparkRegex(domainName,_*) <- sparkRegex.findAllIn("[email protected]"))
    {
      println(domainName)
    }
  }
}

添加公众微信号,可以了解更多最新Spark、Scala相关技术资讯

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 14:53:21

Scala入门到精通——第十二节 I/O与正则表达式的相关文章

Scala入门到精通——第二十二节 高级类型 (一)

作者:摇摆少年梦 视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 this.type使用 类型投影 结构类型 复合类型 1. this.type使用 class Person{ private var name:String=null private var age:Int=0 def setName(name:String)={ this.name=name //返回对象本身 this } def setAge(age:Int)={ this.a

Scala入门到精通——第三十节 Scala脚本编程与结束语

本节主要内容 REPL命令行高级使用 使用Scala进行Linux脚本编程 结束语 1. REPL命令行高级使用 在使用REPL命令行时,有时候我们需要粘贴的代码比较大,而普通的粘贴可能会些一些问题,比如中文粘贴会出现乱码.多行代码粘贴时会出错,此时需要用到REPL的高级功能.在日常开发过程中,我们粘贴多行代码的时候会遇到下列问题: //本意是要粘贴下面两行代码 class Person(val name:String,val age:Int) val p=new Person("摇摆少年梦&q

Scala入门到精通——第十四节 Case Class与模式匹配(一)

本节主要内容 模式匹配入门 Case Class简介 Case Class进阶 1. 模式匹配入门 在java语言中存在switch语句,例如: //下面的代码演示了java中switch语句的使用 public class SwitchDemo { public static void main(String[] args) { for(int i = 0; i < 100; i++) { switch (i) { case 10:System.out.println("10"

Scala入门到精通——第十五节 Case Class与模式匹配(二)

本节主要内容 模式匹配的类型 for控制结构中的模式匹配 option类型模式匹配 1. 模式的类型 1 常量模式 object ConstantPattern{ def main(args: Array[String]): Unit = { //注意,下面定义的是一个函数 //函数的返回值利用的是模式匹配后的结果作为其返回值 //还需要注意的是函数定义在main方法中 //也即scala语言可以在一个函数中定义另外一个函数 def patternShow(x:Any)=x match { ca

Scala入门到精通——第二十七节 Scala操纵XML

本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种非常重要的半结构化数据表示方式,目前大量的应用依赖于XML,这些应用或利用XML作为数据交换格式,或利用XML进行文件配置等.像JAVA.C++及其它流行的程序开发语言都是依赖于第三方库来实现XML的操作,例如JAVA经常通过JDOM,DOM4J等XML处理工具进行XML的操纵,但Scala提供了对XML的原生支持,通过scala.xml._包下的类或

Scala入门到精通——第二十五节 提取器(Extractor)

作者:摇摆少年梦 视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 apply与unapply方法 零变量或变量的模式匹配 提取器与序列模式 scala中的占位符使用总结 1. apply与unapply方法 apply方法我们已经非常熟悉了,它帮助我们无需new操作就可以创建对象,而unapply方法则用于析构出对象,在模式匹配中特别提到,如果一个类要能够应用于模式匹配当中,必须将类声明为case class,因为一旦被定义为case class,

Scala入门到精通——第十七节 类型参数(一)

本节主要内容 类型变量界定(Type Variable Bound) 视图界定(View Bound) 上界(Upper Bound)与下界(Lower Bound) 1. 类型变量界定(Type Variable Bound) 类型变量界定是指在泛型的基础上,对泛型的范围进行进一步的界定,从而缩下泛型的具体范围,例如: //下面的类编译通不过 //因为泛型T在编译的时候不能确定其具体类型 //即并不是所有的类中都存在compareTo方法 class TypeVariableBound { d

Scala入门到精通——第十节 Scala类层次结构、Traits初步

本节主要内容 Scala类层次结构总览 Scala中原生类型的实现方式解析 Nothing.Null类型解析 Traits简介 Traits几种不同使用方式 1 Scala类层次结构 Scala中的类层次结构图如下: 来源:Programming in Scala 从上面的类层次结构图中可以看到,处于继承层次最顶层的是Any类,它是scala继承的根类,scala中所有的类都是它的子类 Any类中定义了下面几个方法: //==与!=被声明为final,它们不能被子类重写 final def ==

Scala入门到精通——第二十八节 Scala与JAVA互操作

本节主要内容 JAVA中调用Scala类 Scala中调用JAVA类 Scala类型参数与JAVA泛型互操作 Scala与Java间的异常处理互操作 1. JAVA中调用Scala类 Java可以直接操作纵Scala类,如同Scala直接使用Java中的类一样,例如: //在Person.scala文件中定义Scala语法的Person类 package cn.scala.xtwy.scalaToJava class Person(val name:String,val age:Int) //伴