最基本讀取檔案的方式, 就是讀取整個檔案到記憶體中去。
Go提供了 ioutil package, 實現了一些實用的I/O函式,以下 利用ioutil.ReadFile
:
package main
import (
"fmt"
"io/ioutil"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
dat, err := ioutil.ReadFile("./test")
check(err)
fmt.Print(string(dat))
}
ioutil.ReadFile
定義:
func ReadFile(filename string) ([]byte, error)
注意引用ioutil是io/ioutil
而不是ioutil
將檔案讀取成byte型式的slice。
檔案不大的時候, ioutil.ReadFile
提供了很方便的選擇, 注意ReadFile成功時候err == nil
而不是err == EOF
。
如果想要對讀取檔案做更多的控制, 那就需要利用Go的 os package, os package提供跟平台有關的操作介面例如檔案操作。 這裡利用os.Open
函式:
import (
"os"
"log"
)
file, err:=os.Open("file.go") //for read access.
defer file.Close()
if err != nil {
log.Fatal(err)
}
注意打開檔案後做完所有處理後, 我們利用defer file.Close()
將開啟的檔案關閉。
打開檔案失敗的話, 錯誤訊息就會自我解釋:
open file.go: no such file or directory
os.Open
傳回一個*File
型別, File
實作io.Reader
interface:
func Open(name string) (file *File, err error)
os.Open
或是os.Create
都是呼叫os.OpenFile
:
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
flag例如是O_RDONLY
只允許讀取, perm像是0666
這樣。os.Open
就是呼叫os.OpenFile, 傳入的flag參數為O_RDONLY
(只允許讀取)。
os.File
可以執行的動作如下:
例如把檔案的資料讀到一個bytes slice, file.Read(data)
傳回讀取到的bytes計數:
data := make([]byte, 100)
count, err := file.Read(data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("read %d bytes: %q\n", count, data[:count])
Go bufio package實作 buffered I/O, 包裹io.Reader
或是io.Writer
變成新的Reader以及Writer, 新的Reader和Writer就提供了buffer的功能, 特別用在文字處理上。
這裡我們使用ReadBytes('\n')
或是ReadString('\n')
或是用Scanner
(簡單使用還是推荐用Scanner)來達成一行一行讀取檔案的目的。
我們利用bufio.NewScnner
取得檔案或是STDIN的*Scanner
。
Scanner
型別提供一個用來讀取資料方便的介面。像是一個用newline符號來分行的文字檔案。#Scanner
Scanner
型別可以使用的function包括:
實作一行一行讀取檔案如下:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
f, err := os.Open("./test")
check(err)
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
利用scanner.Scan()
判定是否還有下一行, 再利用scanner.Text()
或是 scanner.Bytes[]
讀取每行資料。
當然,另外一種作法就是使用ioutil.ReadFile
讀取整個檔案, 再利用strings.Split
切割:
package main
import (
"fmt"
"io/ioutil"
"strings"
)
func main() {
doc, err := ioutil.ReadFile("./test.md")
if err != nil {
panic(err)
}
lines := strings.Split(string(doc), "\n")
for _, line := range lines {
fmt.Printf("%q\n", line)
}
}
問題是這樣最後會多出一行...? .
golang - read text file into string array and write