文件IO

基本的输入输出

可以用scala.io.StdIn.readLine()函数从控制台读取一行输入。如果要读取数字、Boolean或者是字符,可以用readInt、readDouble、readByte、readShort、readLong、readFloat、readBoolean或者readChar。

请看下面的示例:

val input = readLine("请输入内容:")
print("您输入的是:")
println(input)
printf("您的输入内容是%s",input)

执行过程及结果如下:

打开和读取文本文件

有两种方式打开和读取文本文件。

import scala.io.Source

val filename = "fileopen.scala"
for (line <- Source.fromFile(filename).getLines) {
println(line)
}

// 变化的方式
val lines = Source.fromFile("/Users/Al/.bash_profile").getLines.toList
val lines = Source.fromFile("/Users/Al/.bash_profile").getLines.toArray

val fileContents = Source.fromFile(filename).getLines.mkString

关闭文件:

val bufferedSource = Source.fromFile("example.txt")
for (line <- bufferedSource.getLines) {
    println(line.toUpperCase)
}
bufferedSource.close

处理异常:

import scala.io.Source
import java.io.{FileNotFoundException, IOException}

val filename = "no-such-file.scala"
try {
   for (line <- Source.fromFile(filename).getLines) {
      println(line)
   }
} catch {
   case e: FileNotFoundException => println("Couldn't find that file.")
   case e: IOException => println("Got an IOException!")
}

写入文本文件

Scala并没有提供任何特殊的文件与入能力,因此使用Java的PrintWriter或FileWriter:

// PrintWriter
import java.io._

val pw = new PrintWriter(new File("hello.txt" ))
pw.write("Hello, world")
pw.close

// FileWriter
val file = new File(canonicalFilename)
val bw = new BufferedWriter(new FileWriter(file))
bw.write(text)
bw.close()

读写二进制文件

Scala并没有提供任何特殊的方式来读写二进制文件,所以使用Java FileInputStream和 FileOutputStream类:

import java.io._

object CopyBytes extends App {
   var in = None: Option[FileInputStream]
   var out = None: Option[FileOutputStream]
   try {
      in = Some(new FileInputStream("/tmp/Test.class"))
      out = Some(new FileOutputStream("/tmp/Test.class.copy"))
      var c = 0
      while ({c = in.get.read; c != −1}) {
          out.get.write(c)
      }
   } catch {
       case e: IOException => e.printStackTrace
   } finally {
       println("entered finally ...")
       if (in.isDefined) in.get.close
       if (out.isDefined) out.get.close
   }
}

处理CSV文件

例如:

January, 10000.00, 9000.00, 1000.00
February, 11000.00, 9500.00, 1500.00
March, 12000.00, 10000.00, 2000.00

按行处理:

object CSVDemo extends App {
    println("Month, Income, Expenses, Profit")
    val bufferedSource = io.Source.fromFile("/tmp/finance.csv")
    for (line <- bufferedSource.getLines) {
       val cols = line.split(",").map(_.trim)
       // do whatever
       println(s"${cols(0)}|${cols(1)}|${cols(2)}|${cols(3)}")
    }
    bufferedSource.close
}

如果不想使用数组访问,可以使用如下的for循环:

for (line <- bufferedSource.getLines) {
   val Array(month, revenue, expenses, profit) = line.split(",").map(_.trim)
   println(s"$month $revenue $expenses $profit")
}

如果有标题行,可以这样处理:

for (line <- bufferedSource.getLines.drop(1)) { 
   // ...
}

如果愿意,还可以写成foreach循环:

bufferedSource.getLines.foreach { line =>
   rows(count) = line.split(",").map(_.trim)
   count += 1
}

《Spark原理深入与编程实战》