package com.datacrafts.digitalevers.curry
import java.io.{BufferedReader, Closeable, File, FileReader}
import com.esotericsoftware.minlog.Log
/**
* 这段代码使用函数柯里化的功能实现了读取文件源并将其转为List数据
*
* 函数柯里化的精髓是使得函数在依赖其他函数的情况下实现可插拔,从而在函数与函数之间的调用上进行解耦
* 比如这段代码也可以在getLines底层函数上只保留 filename 一个参数,在函数体内直接调用 isReadable 和 closeStream 方法来进行
* 周边逻辑的实现,可以达到同样的效果,但是如果将来需要修改 isReadable 和 closeStream 的功能,不得不修改这两个方法的源代码
* 如果采用柯里化的形式 可以重新编写一个 isReadable 和 closeStream 的实现,在上层调用的时候直接将新函数作为参数传入即可
* 从而符合ocp原则。
*/
object File2List {
def main(args: Array[String]): Unit = {
var list = readFile("1.txt")
print(list)
}
def readFile (filename: String): List[String] = {
getLines(filename) (isReadable) (closeStream)
}
/**
* 柯里化后的函数
* @param filename
* @param isFileReadable
* @param closableStream
* @return
*/
private def getLines (filename: String) (isFileReadable: (File) => Boolean) (closableStream: (Closeable) => Unit): List[String] = {
val file = new File(filename)
if (isFileReadable (file) ) {
val readerStream = new FileReader(file)
val buffer = new BufferedReader(readerStream)
try {
var list: List[String] = List ()
var str = ""
var isReadOver = false
while (! isReadOver) {
str = buffer.readLine ()
if (str == null) isReadOver = true
else list = str :: list
}
list.reverse
} finally {
closableStream (buffer)
closableStream (readerStream)
}
} else {
List ()
}
}
/**
* 判断文件是否可读
* @param file
* @return
*/
def isReadable (file: File) = {
if (null != file && file.exists() && file.canRead() ) {
true
} else {
false
}
}
/**
*关闭打开的文件流
* @param stream
*/
def closeStream (stream: Closeable) {
if (null != stream) {
try {
stream.close
} catch {
case ex => Log.error( "[" +this.getClass.getName + ".closeStream] ", ex.getMessage)
}
}
}
}