focus onjava
Source.fromFile(..).getLines.toArray 输出文件的全部行正则表达式
Source.fromFile(..).mkString 以字符串形式输出文件内容数组
将字符串转换为数字, 能够用 toInt 或 toDouble 方法app
使用 Java 的 PrintWriter 来写入文本文件ide
"正则".r 是一个 Regex 对象spa
正则表达式 包含 或者 “ , 使用 """..."""scala
若是正则模式包含分组, 你能够用以下语法来提取它们的内容 for (regex(变量1, ...) <- 字符串)rest
import java.io.PrintWriter import java.io.File import scala.io.Source object HelloFile extends App { val writer = new PrintWriter(new File("test.txt")) // base dir will generate test.txt writer.write("Hello Scala In test.txt") writer.close() // 9.0 console read print("Please enter your input : ") val line = Console.readLine println("Thanks, you just typed: " + line) // 9.1 Read File content println("Following is the content read:") Source.fromFile("test.txt").foreach { print } // mkString / Array val source = Source.fromFile("test.txt") val contents = source.mkString // // val arr = source.getLines().toArray // println("\n\ncontents : " + contents + "\n") // // println("\n\narr : " + arr) source.close() // 9.2 读取字符 val source2 = Source.fromFile("test.txt") val iterator = source2.buffered while (iterator.hasNext) { if (iterator.head != 'e') { print(iterator.next()) } else { iterator.next() } } source2.close() }
object ReadLine extends App { val source = Source.fromFile("num.txt", "UTF-8") // 9.3 读取词法单元 和 数字 val tokens = source.mkString.split("\\s+") val numbers = tokens.map(_.toDouble) for (w <- numbers) { println(w) } /* Output 12.0 34.0 56.0 78.0 89.0 */ source.close() println("haow old are you ?") val age = readInt() println("age : " + age) // 9.4 从 URL 或 其余源 读取 val source1 = Source.fromURL("http://52binge.com", "UTF-8") // URL 须要事先 知道字符集 val source2 = Source.fromString("Hello,World") val source3 = Source.stdin }
object BinaryFileAndPrintWriteFile extends App { // 9.5 读取二进制文件 (使用Java类库) val file = new File("num.txt") val in = new FileInputStream(file) val bytes = new Array[Byte](file.length().toInt) // File readTo 字符数组 in.read(bytes) for (c <- bytes) { println(c.toChar) } in.close() // 9.6 写入文本文件 val out = new PrintWriter("numbers.txt") for (i <- 1 to 10) { out.println(i) } out.close() }
object DirSerialize { // 9.7 访问目录, (Scala不是很是方便) // 9.8 序列化 // 1. Java 序列化, public class Person implements java.io.Serializable // 2. 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 FileOInputStream("/tmp/test.obj")) val savedFred = in.readObject().asInstanceOf[person] */ // Scala 集合类都是可序列化的, 所以 你能够把它们用作你的可序列化类的成员 /* class Person extends Serializable { private val friends = new ArrayBuffer[Person] // ok--ArrayBuffer 是可序列化的 */ }
object Match extends App { val numPattern = "[0-9]".r val wsnumwsPattern = """\s+[0-9]+\s""".r for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles")) { println(matchString) } for (matchString <- wsnumwsPattern.findAllIn("99 bottles, 998 9bottles")) { println("B" + matchString + "B") } // 9.10 正则 表达式 组 val numitemPattern = "([0-9]+) ([a-z]+)".r val numitemPattern(num, item) = "99 bottles" for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 998 9bottles")) { println(num + " " + item) } }
MyGithub日志
focus oncode
Class 能够实现任意数量的 Trait
Trait 能够要求实现它们的 Class 具有特定的 字段、方法、超类
Scala Trait 可提供 方法 和 字段 的实现
多个 Trait 叠加, 顺序很重要。 方法 先被执行的 Trait 排在更后面
Scala 提供 “Trait” 而非 Interface。Trait 可同时提供 抽象方法 和 具体方法, 而 Class 能够实现多个 Trait
trait Logger { def log(msg: String) // 这是个抽象方法, 你不须要声明为 abstract, 特质中未被实现的方法就是 抽象方法 } /** * Date : 2016-04-07 * 全部的 Java 接口 均可以 做为 Scala trait 使用 */ class ConsoleLogger extends Logger with Cloneable with Serializable { // use extends def log(msg: String): Unit = { // 重写 Trait 的 抽象方法 不须要给出 override 关键字 println(msg) } // 和 Java 同样, Scala 类 只能有一个 超类, 但 能够有 任意数量的 Trait }
trait Logged { def log(msg: String) {} } trait ConsolePrintLogger extends Logged { override def log(msg: String): Unit = { println(msg) } }
class SavingsAccount extends Account with ConsolePrintLogger { def withdraw(amount: Double): Unit = { if (amount > balance) { log("Insufficient funds") } else { balance -= amount } } // 注 : 让 Trait 存在具体行为存在一个 弊端. 当 Trait 改变时, 全部混入了该 Trait 的 Class 都必须 re compile }
class SavingsAcc extends Account with Logged { def withdraw(amount: Double): Unit = { if (amount > balance) { log("Insufficient funds") } else { balance -= amount } } } // 看上去,毫无心义, 其实否则,你能够在 构造对象 的时候 "混入" 一个更好的 日志 记录器 object SavingsAcc extends App { val acct1 = new SavingsAcc with ConsolePrintLogger // val acct2 = new SavingsAcc with FileLogger acct1.withdraw(100) }
你能够为 Class 或 Object 添加多个互相调用的特质。
trait TimestampLogger extends Logged { override def log(msg: String) { super.log(new java.util.Date() + " " + msg) } }
trait ShortLogger extends Logged { val maxLength = 15 // 关于 Trait 的 Field override def log(msg: String) { super.log(if (msg.length <= maxLength) msg else msg.substring(0, maxLength - 3) + "...") } }
上述 log 方法 每个都将修改过的消息传递给 super.log
对 Trait 而言, super.log 并不像 Class 那样拥有相同的含义。
实际上, super.log 调用的是 Trait层级 中的下一个 Trait,具体是哪个具体 Trait 的顺序决定
val acct1 = new SavingsAccount with ConsolePrintLogger with TimestampLogger with ShortLogger
output :
Sun Feb 06 17:45:45 ICT 2011 Insufficient...
trait Logger { def log(msg: String) // 这是个抽象方法 }
trait TimestampLogger extends Logged { override def log(msg: String) { super.log(new java.util.Date() + " " + msg) } }
编译器将 super.log 调用标记为 错误。Logger.log 方法没有实现。咱们无法知道哪一个 log 方法会被调用
Scala 认为 TimestampLogger 依然是 抽象 的, 由于你必须给 方法 打上 abstract override
trait TimestampLogger extends Logged { abstract override def log(msg: String) { super.log(new java.util.Date() + " " + msg) } }
trait Logger { def log(msg: String) def info(msg: String) { log("INFO: " + msg) } def warn(msg: String) { log("WARN: " + msg) } def severe(msg: String) { log("SEVERE: " + msg) }
使用 Logger 的 Class 就能够任意 调用这些 log 方法了。
class SavingsAccount extends Account with Logged { def withdraw(amount: Double): Unit = { if (amount > balance) { severe("Insufficient funds") } else { balance -= amount } } ... override def log(msg: String) { println(msg); } }
Scala 这种 Trait 使用 具体 和 抽象 方法随处可见
Trait 中的 Field 能够是具体的,也能够是抽象的。
trait ShortLogger extends Logged { val maxLength = 15 // 具体的字段 ... }
class SavingsAccount extends Account with ConsolePrintLogger with ShortLogger { var interest = 0.0 def withdraw(amount: Double): Unit = { if (amount > balance) { log("Insufficient funds") } else { balance -= amount } } }
你能够把具体的特质字段当作是针对使用该特质的类的 “装配指令”。任何混入的字段都自动成为该类 本身 的 字段
Trait 中未被初始化的字段,在具体的子类中 必须被 override (不须要写该关键字)
trait ShortLogger extends Logged { val maxLength: Int // 抽象字段 override def log(msg: String) { super.log( if (msg.length <= maxLength) msg else msg.substring(0, maxLength - 3 ) + "..." ) // 实现中使用了 maxLength } ... }
在 一个 具体的 Class 使用该 Trait 中,你必须提供 maxLength 字段
class SavingsAccount extends Account with ConsoleLogger with ShortLogger { val maxLength = 20 // 不须要写 override ... }
trait FileLogger extends Logger { val out = new PrintWrite("app.log") // 这是 特质构造器的一部分 out.println("# " + new Date().toString) // 一样是特质构造器的一部分 def log(msg: String) { out.println(msg) out.flush() } }
构造顺序
class SavingsAccount extends Account with FileLogger with ShortLogger
Account (超类)
Logger (第一个 Trait 的 父 Trait)
FileLogger (第一个 Trait)
ShortLogger (第二个 Trait)。 注意 它的 父trait Logger 已被构造
SavingsAccount (Class)
说明 : 构造器的顺序是 类 的 线性化 的反向
Trait 不能有构造器参数. 每一个 Trait 都有一个无参数的构造器
说明 : 缺乏构造器参数是 Trait 与 Class 的惟一技术差异
这个局限对于那些须要某种定制才有用的 Trait 来讲会是一个问题
trait 能够扩展另外一个 trait, 而由 trait 组成的继承层级也很常见。而由 trait 扩展 class, 这个 class 会自动成为全部混入该 trait 的 超类