本章主要说的是文件的相关操作,和正则表达式
本章要点:
- 文件操作
- 序列化
- 正则表达式
13.1 文件操作
13.1.1 文件读取
import scala.io.Source
object Test {
def main(args: Array[String]): Unit = {
val source = Source.fromFile("D:\\58\\workspace\\scala-study\\src\\data.txt", "UTF-8")//第一个参数可以是字符串或者是java.io.File
val iterator=source.getLines();
while(iterator.hasNext){
print(iterator.next())
}
source.close()
}
}
或者你也可以对迭代器应用toArray或toBuffer方法,将这些行放到数组或数组缓冲当中:
val source = Source.fromFile("D:\\58\\workspace\\scala-study\\src\\data.txt", "UTF-8")
var arr= source.getLines().toArray
for(x<-arr){
println(x)
source.close()
有时候,你只想把整个文件读取成一个字符串:
val contents=source.mkString
需要注意的是,在用完Source的对象后,记得调用close。
这里有一个快而脏的方式来读取源文件中所有以空格隔开的词法单元:
val tokens = source.mkString.split("\\S+")
从URL或其他源读取
Source对象有读取非文件源的方法:
val source1 = Source.fromURL("http://horstamnn.com", "UTF-8")
val source2 = Source.fromString( "Hello, World! " ) // 从给定的字符串读取,这对调试很有用
val source3 = Source.stdin //从标准输入读取
当你从URL读取时,你需要事先知道字符集,可能是通过HTTP头获取。
读取二进制文件
Scala并没有提供读取二进制文件的方法。你需要使用Java类库。以下是如何将文件读取成字节数组:
val file = new File (filename)
val in = new FileInputStream(file)
val bytes = new Array[Byte](file.length.tolnt)
in.read (bytes)
in.close()
写入文本文件
Scala没有内建的对写入文件的支持。要写入文本文件,可使用java.io.PrintWriter,例如:
val out = new PrintWriter("numbers.txt")
for (i <- 1 to 5) out.println("我们不一样")
out.close()
访问目录
class Test{
}
object Test{
def subDir(dir:File):Iterator[File] ={
val children = dir.listFiles().filter(_.isDirectory())
children.toIterator ++ children.toIterator.flatMap(subDir _)
}
def subFile(dir:File):Iterator[File] ={
val dirs = dir.listFiles().filter(_.isDirectory())
val files = dir.listFiles().filter(_.isFile())
files.toIterator ++ dirs.toIterator.flatMap(subDir _)
}
//遍历某目录下所有的文件和子文件
def main(args:Array[String]):Unit = {
for(d <- subFile(new File("D:\\data")))
println(d)
}
}
13.2 序列化
Serializable特质定义在scala包,因此不需要显式引入。如果你能接受缺省的ID,也可略去@SerialVersionUID注解。你可以按照常规的方式对对象进行序列化和反序列化:
@SerialVersionUID(42L) class Person extends Serializable{
private var name:String="";
}
13.3 正则表达式
当你在处理输入的时候,你经常会想要用正则表达式来分析它。scala.util.matching.Regex类让这件事情变得简单。要构造一个Regex对象,用String类的r方法即可:
val numPattern="[0-9]+ ".r
如果正则表达式包含反斜杠或引号的话,那么最好使用"原始"字符串语法。例如:
val wsnumwsPattern = """\s+[0-9]+\s+""".r // 和"\\s+[0-9]+\\s+".r相比要更易读一些
findAllln方法返回遍历所有匹配项的迭代器。你可以在for循环中使用它:
for ( matchString <- numPattern.findAllln( "99 bottles, 98 bottles")){
处理matchString
}
或者将迭代器转成数组:
val matches = numPattern.findAllln("99 bottles, 98 bottles").toArray // Array(99, 98)
要找到字符串中的首个匹配项,可使用findFirstln。你得到的结果是一个Option[String]
val ml = wsnumwsPattern.findFirstln("99 bottles, 98 bottles") //Some("98")
要检查是否某个字符串的开始部分能匹配,可用findPrefixOf:
numPattern.findPreflxOf("99 bottlesf 98 bottles") //Some(99)
wSnumwsPattern.findPrefixOf("99 bottles, 98 bottles") // None
你可以替换首个匹配项,或全部匹配项:
numPattern.replaceFirstln("99 bottles, 98 bottles", "XX")
// "XX bottles, 98 bottles"
numPattern. replaceAllIn("99 bottles, 98 bottles", "XX")
// "XX bottles, XX bottles"
正则表达式组
分组可以让我们方便地获取正则表达式的子表达式。在你想要提取的子表达式两侧加上圆括号,例如:
val numitemPattern = " ([0-9]+) ([a-z]+) ".r
要匹配组,可以把正则表达式对象当做"提取器"使用,就像这样:
val numitemPattern (num, item) = "99 bottles"
// 将num设为"99",item设为"bottles"
如果你想要从多个匹配项中提取分组内容,可以像这样使用for语句:
for (numitemPattern (num,item) <- numitemPattern.findAllln("99 bottles, 98 bottles")){
//处理num和item
}
网友评论