本章要點(diǎn)
- Source.fromFile(...).getLines.toArray 輸出文件文件的所有行
- Source.fromFile(...).mkString 以字符串形式輸出文件內(nèi)容
- 將字符串轉(zhuǎn)換為數(shù)字顷锰,可以用toInt或toDouble方法
- 使用Java的PrintWriter來(lái)寫(xiě)入文本文件- “正則”.r 是一個(gè)Regex對(duì)象
- 如果你的正則表達(dá)式包含反斜杠或引號(hào)的話鼻种,用"""..."""
- 如果正則模式包含分組缔俄,你可以使用如下語(yǔ)法來(lái)提取它們的內(nèi)容 for (regex(變量1, ..., 變量n) <- 字符串)
讀取行
使用scala.io.Source 對(duì)象的getLines方法
import scala.io.Source
val source = Source.fromFile("myfile.txt", "UTF-8")
val lineIterator = source.getLines
for (line <- lineIterator) println(line)
// 或者將這些行放到數(shù)組或數(shù)組緩沖
val lines = source.getLines.toArray
// 使用完畢后關(guān)閉Source對(duì)象
source.close
讀取字符
直接把source對(duì)象當(dāng)做迭代器來(lái)從文件中讀取單個(gè)字符:
for (c <- source) 處理c
source對(duì)象的buffered方法可以獲得一個(gè)BufferedIterator[A]迭代器,使用它的head方法可以查看下一個(gè)字符,但不會(huì)把它當(dāng)做以處理的字符:
import scala.io.Source
val source = Source.fromFile("myfile.txt", "UTF-8")
val iter = source.buffered
while (iter.hasNext) {
if (iter.head 是符合預(yù)期的) {
處理 iter.next
} else {
iter.next
...
}
}
source.close
注意: 在else分之必須有iter.next或者while循環(huán)中有跳出循環(huán)的語(yǔ)句饲漾,否則將很可能陷入死循環(huán)。
如果文件不大,也可以讀取成字符串處理:
val contents = source.mkString
讀取詞法單元和數(shù)字
val tokens = source.mkString.split("\\s+") // 以空格隔開(kāi)的詞法單元
// 轉(zhuǎn)換成Double類型
val numbers = for (w <- tokens) yield w.toDouble
// 或者
val numbers = tokens.map(_.toDouble)
從控制臺(tái)讀取數(shù)字
print ("How old are you? ")
val age = readInt() // readLong or readDouble 這種方法假定了下一行輸入只包含單個(gè)數(shù)字坤按,
// 且前后沒(méi)有空格,否則會(huì)拋出異常:NumberFormatException
從URL或其他源讀取
val source1 = Source.fromURL("http://horstamnn.com", "UTF-8")
val source2 = Source.fromString("Hello, World")
val source3 = Source.stdin
...
source1.close
source2.close
source3.close
讀取二進(jìn)制文件
Scala沒(méi)有提供讀取二進(jìn)制文件的方法馒过,需要使用Java的類庫(kù)
val file = new File(filename)
val in = new FileInputStream(file)
val bytes = new Array[Byte] (file.length.toInt)
in.read(bytes)
in.close
寫(xiě)入文本文件
Scala同樣沒(méi)有內(nèi)建的對(duì)寫(xiě)入文件的支持臭脓,需要使用java.io.PrintWriter:
val out = new PrintWriter("numbter.txt")
for (i <- 1 to 100) out.println(i)
out.close
PrintWrite的printf方法比較特殊,需要你將參數(shù)轉(zhuǎn)換成AnyRef才可以:
out.printf("%6d %10.2f", quantity.asInstanceOf[AnyRef], price.asInstanceOf[AnyRef])
// 為了避免這個(gè)麻煩腹忽,可以使用String類的format方法:
out.print("%6d %10.2f".format(quantity, price))
訪問(wèn)目錄
目前Scala沒(méi)有正式的用來(lái)訪問(wèn)某個(gè)目錄中的所有文件来累,或者遞歸的遍歷所有目錄。
import java.io.File
def subdirs(dir: File): Iterator[File] = {
val children = dir.listFiles.filter(_.isDirectory)
children.toIterator ++ children.toIterator.flatMap(subdirs _)
}
// 訪問(wèn)所有子目錄
for (d <- subdirs(dir)) 處理 d
序列化
在Java中窘奏,我們用序列化來(lái)將對(duì)象傳輸?shù)狡渌摂M機(jī)嘹锁,或者臨時(shí)存儲(chǔ)。
// Java
public class Person implements java.io.Serializable {
private static final long serialVersionUID = 42L;
...
}
// Scala
@SerialVersionUID(42L) class Person extends Serializable
val fred = new Person(...)
import java.io._
val out = new ObjectOutputStream(new FileOutputStream("/tmp/test.obj"))
out.writeObject(fred)
out.close()
val in = new ObjectInputStream(new FileInputStream("/tmp/test.obj"))
val savedFred = in.readObject().asInstanceOf[Person]
Scala的集合類都是可序列化的着裹,因此你可以把它們用做你的可序列化類成員:
class Person extends Serializable {
private val friends = new ArrayBuffer[Person]
...
}
正則表達(dá)式
使用scala.util.matching.Regex類
val numPattern = "[0-9]".r
val wsnumwsPattern = """\s+[0-9]\s""".r // 處理反斜杠或引號(hào)
// findAllIn方法返回遍歷所有匹配項(xiàng)的迭代器
for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles")) 處理matchString
// 將迭代器轉(zhuǎn)換為數(shù)組
val matches = numPattern.findAllIn("99 bottles, 98 bottles")).toArray // Array(99, 98)
// 找到字符串的首個(gè)匹配項(xiàng):
val m1 = wsnumwsPattern .findFirstIn("99 bottles, 98 bottles") // Some(" 98 ")
// 檢查是否某個(gè)字符串的開(kāi)始部分能匹配
numPattern.findPrefixOf("99 bottles, 98 bottles") // Some(99)
wsnumwsPattern .findPrefixOf("99 bottles, 98 bottles") // None
// 替換
numPattern.replaceFirstIn("99 bottles, 98 bottles", XX) // "XX bottles, 98 bottles"
numPattern.replaceAllIn("99 bottles, 98 bottles", XX) // "XX bottles, XX bottles"
正則表達(dá)式組
分組可以讓我們方便的獲取正則表達(dá)式的子表達(dá)式领猾。要提取的子表達(dá)式兩側(cè)加上圓括號(hào),例如:
val numitemPattern = "([0-9]+) ([a-z]+)".r
// 要匹配組骇扇,可以把正則表達(dá)式對(duì)象當(dāng)做"提取器"使用
val numitemPattern(num, item) = "99 bottles" // 將num設(shè)為"99", item設(shè)為"bottles"
for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 98 bottls")) {
處理num和item
}