《快学Scala》——文件和正则表达式、特质

2019-03-28

读取行

要读取文件中的所有行,可以调用scala.io.Source对象的getLines方法:

fromFile方法中会传入两个参数,第一个参数可以是字符串或者是java.io.File,如果你知道文件使用的是当前平台缺省的字符编码,则可以省略第二个参数。
也可以使用toArray或者toBuffer方法,将这些行放入数组或数组缓冲区中:

也可以直接将整个文件读取成字符串:

注: 在用完Source对象后要调用close

读取字符

要从文件中读取单个字符,你可以直接将Source对象当作迭代器,因为Source扩展自Iterator[Char]for (c <- source) 处理c

// 统计某个文件中包含字符'a'的个数
val source = Source.fromFile("...")
val iter = source.buffered
var sum = 0
while (iter.hasNaxt) {
    if (iter.head == 'a') {
        sum = sum + 1
    }
    println(iter.next())
}
println("sum:" + sum)
source.close()

读取词法单元和从URL或其他源读取

可以使用如下方式读取文件中所有以空格隔开的词法单元:
val tokens = source.mkString.split(“\\S+”)
Source对象有读取非文件源的方法:

val source1 = Source.fromURL(“一个URL地址”,”UTF-8”)
val source2 = Source.fromString(“Hello World!”) // 从给定的字符串读取

终端输入: 早期的Scala中Console类提供了一系列的终端输入方法,在现在的版本中这些方法已经被废弃。

  • 当前版本的Scala获取终端输入需要使用包scala.io.StdIn中的相关方法。
  • scala.io.StdIn中的相关方法签名与先前的Console类中完全相同。
  • 使用readLine()获取单行文本输入,返回String类型。
  • 使用readInt()/readFloat()/readChar()/readLong()...等方法获取特定类型的输出,当输入的内容不匹配时,会抛出异常。
  • 使用readf()/readf1()/readf2()/readf3()等方法能以java.text.MessageFormat语法格式化接收的终端输入。

注: Scala中没有提供读取二进制文件的方法,但是可以用Java的类库。

写文件

// 将1-10数字写到文件中
val out = new PrintWriter(fileName="...")
for (i <- 1 to 10) out.println(i)
out.close()

特质

一个类扩展自一个或多个特质,以便使用这些特质提供的服务。特质可能要求使用它的类支持某个特定的特性。不过,和Java接口不同,Scala可以给出这些特性的缺省实现。特质还可以扩展类,这个类将会成为所有混入该特质的超类。
注: Scala和Java一样不支持多继承。在第一个特质前使用extends,然后再剩下的特质前使用with

特质构造顺序

和类一样,特质也可以有构造器,由字段的初始化和其他特质体中的语句构成。构造器的执行顺序如下:

  • 首先调用超类的构造器。
  • 特质构造器在超类构造器之后、类构造器之前执行。
  • 特质由左到右被构造。
  • 每个特质当中,父特质先被构造。
  • 如果多个特质共有要给父特质,而那个父特质已经被构造,则不会被再次构造。
  • 所有特质构造完毕,子类被构造。

举例来说,如下:
class SavingsAccount extends Account with FileLogger with ShortLogger
构造器将按照如下顺序执行:

  • Account(超类)
  • Logger(第一个特质的父特质)
  • FileLogger(第一个特质)
  • ShortLogger(第二个特质),注意它的父特质已经被构造
  • SavingsAccount(类)

注: 特质不能有构造参数。每个特质都有一个无参数的构造器。