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相关类有个比较深入的了解。
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进行互操作。
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(); } }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) } }在众多的编程语言当中,包括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 前一个匹配的结束
下面给出最为常用的几种正则表达式的操作来领略正则表达式的魅力及它在scala中是如何使用的。 1 匹配邮箱:
object RegexMatch { def main(args: Array[String]): Unit = { val sparkRegex="^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$".r for(matchString <- sparkRegex.findAllIn("zhouzhihubeyond@sina.com")) { 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("zhouzhihubeyond@sina.com")) { println(domainName) } } }添加公众微信号,可以了解更多最新Spark、Scala相关技术资讯
