使用Groovy開發之I/O

Groovy提供了一些輔助方法來幫助開發者開發I/O程序,開發過程中你可以使用標準的java代碼,但Groovy提供了更多簡便的方法來處理files、streams、readers,一起來看一下。

1、讀取文件

def baseDir = "/Users/jiangxiaoma/Documents"
new File(baseDir, 'test.txt').eachLine { line ->
    println line
}

eachLine方法是被Groovy自動添加到File類的方法并有不同版本,比如要加上行號,你可以這樣:

new File(baseDir, 'test.txt').eachLine { line, nb ->
    println "Line $nb: $line"
}

eachLine閉包內發生任何異常,該方法都能確保源文件被正常關閉。

在某些情況下你可能使用Reader,你仍將從Groovy的自動資源管理中獲益,下面的例子,如果發生異常,reader將自動被關閉:

def count = 0, MAXSIZE = 3
new File(baseDir,"test.txt").withReader { reader ->
    while (reader.readLine()) {
        if (++count > MAXSIZE) {
            throw new RuntimeException('Test.txt should only have 3 verses')
        }
    }
}

如果你想把文件內容各行放進一個list,你可以這樣:

def list = new File(baseDir, 'test.txt').collect {it}

或者你可以使用as將文件內容放入一個array:

def array = new File(baseDir, 'test.txt') as String[]

如果想把文件內容直接放進一個byte[],可以這樣:

def file = new File(baseDir, 'test.txt')
byte[] contents = file.bytes

在進行I/O操作的時候不僅限于文件,事實上,很多操作都依賴于輸入輸出流,下面例子是從File中獲取InputStream

def is = new File(baseDir,'test.txt').newInputStream()
// do something ...
is.close()

這種方式需要自己手動關閉流,使用withInputStream方法將會自動關閉流:

new File(baseDir,'haiku.txt').withInputStream { stream ->
// do something ...
}

2、寫入文件

在某些情況下,你可能不僅需要讀取文件,也要寫入文件,寫入文件使用Writer

new File(baseDir,'test.txt').withWriter('utf-8') { writer ->
    writer.writeLine 'Into the ancient pond'
    writer.writeLine 'A frog jumps'
    writer.writeLine 'Water’s sound!'
}

更簡單的方法是使用<<操作符:

new File(baseDir,'test.txt') << '''Into the ancient pond
    A frog jumps
    Water’s sound!'''

如果你的test.txt里有內容,上面兩種方式將會覆蓋test.txt的內容。

當然你也可以直接用輸出流來寫入文件:

def os = new File(baseDir,'data.bin').newOutputStream()
// do something ...
os.close()

同樣的,withOutputStream方法將自動關閉輸出流和處理異常:

new File(baseDir,'data.bin').withOutputStream { stream -> 
// do something ...
}

3、遍歷文件樹

遍歷文件夾是一個經常用到的功能,Groovy提供了一些方法來遍歷,比如列出根目錄下的所有文件和文件夾、找到符合正則表達式的標題的文件:

def dir = new File("/")
//eachFile()方法返回該目錄下的所有文件和子目錄,不遞歸
dir.eachFile { file ->
    println file.name
}
dir.eachFileMatch(~/.*\.txt/) {file ->
    println file.name
}

可能你需要處理更深目錄層次的文件,或者只顯示文件或者文件夾,你可以使用eachFileResource

def dir = new File("/")
//dir.eachFileRecurse()方法會遞歸顯示該目錄下所有的文件和目錄
dir.eachFileRecurse { file ->
    println file.name
}
dir.eachFileRecurse(FileType.FILES) { file ->
    println file.name
}

一些更復雜的遍歷方法你可以使用traverse方法,但需要你設置一個特殊的標志指示如何遍歷:

dir.traverse { file ->
    //如果當前文件是一個目錄且名字是bin,則停止遍歷
    if (file.directory && file.name=='bin') {
        FileVisitResult.TERMINATE
    //否則打印文件名字并繼續
    } else {
        println file.name
        FileVisitResult.CONTINUE
   }
}

4、數據和類的序列化&反序列化

在java中使用java.io.DataOutputStreamjava.io.DataInputStream進行序列化和反序列化是非常常用的,使用Groovy將使之變得更容易,下面是序列化數據到文件和從文件讀取數據進行反序列化:

boolean b = true
String message = 'Hello from Groovy'
def file = new File(baseDir, 'test.txt')
// 序列化數據到文件
file.withDataOutputStream { out ->
    out.writeBoolean(b)
    out.writeUTF(message)
}
// ...
// 從文件讀取數據并反序列化
file.withDataInputStream { input ->
    assert input.readBoolean() == b
    assert input.readUTF() == message
}

同樣的,如果一個類實現了Serializable接口,可以將對象序列化到文件:

def file = new File(baseDir, 'test.txt')
Person p = new Person(name:'Bob', age:76)
// 序列化對象到文件
file.withObjectOutputStream { out ->
    out.writeObject(p)
}
// ...
// 從文件讀取數據進行反序列化
file.withObjectInputStream { input ->
    def p2 = input.readObject()
    assert p2.name == p.name
    assert p2.age == p.age
}

5、程序中執行shell命令

Groovy提供了簡單的方法執行shell命令:

def process = "ls -l".execute()
println "Found text ${process.text}"

//逐行處理
def process = "ls -l".execute()
process.in.eachLine { line ->
    println line
}

execute()方法返回了一個java.lang.Process實例。

如果想執行windows下的dir命令:

def process = "dir".execute()
println "${process.text}"

將返回IOExcepton異常:“Cannot run program "dir": CreateProcess error=2, The system cannot find the file specified.
這是因為dir命令是windows下的shell命令(cmd.ext),不能執行,應該這樣寫:

def process = "cmd /c dir".execute()
println "${process.text}"
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,925評論 6 342
  • ———形式上跟隨潮流,內容上跟隨理想 今天看到了兩句話,感覺特別震撼?!敖o客戶想要的東西,比給客戶事實更能賺錢” ...
    好奇動物閱讀 884評論 0 1
  • 天亮了,推開窗,幾只鳥兒在唱歌,聽得出那是歡樂的歌曲。眼前的景色大不一樣了。十年前,眼前的景色是一片多姿多彩的菜地...
    Sunshine陳閱讀 267評論 0 0
  • 文/閑云野鶴秋錦 是命運的安排 還是純粹的偶然 你我相逢于街道 你不認識我 我不認識你 你我相逢在路上 日日相見卻...
    東豐閑云野鶴閱讀 277評論 0 0