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 FileReader {
/**
* 柯里化后的函数
* @param filename
* @param isFileReadable
* @param closableStream
* @return
*/
def getLines (filename: String) (isFileReadable: (File) => Boolean) (closableStream: (Closeable) => Unit): String = {
val file = new File(filename)
if (isFileReadable (file) ) {
val readerStream = new FileReader(file)
val buffer = new BufferedReader(readerStream)
try {
var content = ""
var str = ""
var isReadOver = false
while (! isReadOver) {
str = buffer.readLine ()
if (str == null) {
isReadOver = true
} else {
content += str
}
}
content
} finally {
closableStream (buffer)
closableStream (readerStream)
}
} else {
""
}
}
/**
* 判断文件是否可读
* @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:Throwable => Log.error( "[" +this.getClass.getName + ".closeStream] ", ex.getMessage)
}
}
}
}