《快学Scala》——文件和正则表达式、特质
读取行
要读取文件中的所有行,可以调用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(类)
注: 特质不能有构造参数。每个特质都有一个无参数的构造器。