Go語言下的文件讀寫操做

在Go語言中,文件是使用一個os.File類的對象指針表示的,也能夠稱這指針爲文件句柄(filehandle),os.Stdin和os.Stdout也是屬於這個*os.File類型的。web

下面舉例說明windows

package main


import (

    "bufio"

    "fmt"

    "io"

    "os"

)


func main() {

    inputFile, inputError := os.Open(os.Args[1])//變量指向os.Open打開的文件時生成的文件句柄

    if inputError != nil {

        fmt.Printf("An error occurred on opening the inputfile\n")

        return

    }

    defer inputFile.Close()


    inputReader := bufio.NewReader(inputFile)

    lineCounter := 0

    for {

        inputString, readerError := inputReader.ReadString('\n')

        //inputString, readerError := inputReader.ReadBytes('\n')             if readerError == io.EOF {

            return

        }

        lineCounter++

        fmt.Printf("%d : %s", lineCounter, inputString)

    }

}

上例中的的inputFile是一個*os.File的類型變量,它指向一個打開的文件描述符(文件句柄)。os.Open函數接受一個文件名做爲參數,上例中使用的是os.Args[1]的命令行裏的第一個參數,os.Args[0]指程序自己。 使用os.Open打開的文件爲只讀模式,另一個函數OpenFile(name string, flag int, perm FileMode) (file *File, err error) 指代更多的操做模式。當要打開的文件不存在或程序沒有足夠權限時,會報錯。defer.Close()函數的做用是爲了保證程序結束前,這個被打開的文件能爲關閉。關鍵字defer具備延遲執行功能。經過bufio.NewReader(inputFile),咱們得到一個帶緩衝的reader。之因此轉換爲使用bufio包裏的reader(或者writer),是由於這樣咱們就可使用一些實用的高級別的字符串對象,而不是底層原始的bytes數據。接着,使用ReadString('\n')或者ReadBytes('\n')方法無限循環一行行地讀文件內容,值得注意的是,不管是unix系統仍是windows系統,ReadString、ReadBytes還有ReadLine都能經過'\n'識別爲換行。當咱們讀取文件直到文件結束時,readerError !=nil (readerError==io.EOF),這個for 循環便結束了。數組


這裏還有一些可代替的方法app

一、能夠以字符串(字節串)方式一次性讀一個完整文件的內容,io/ioutil包裏的ioutil.ReadFile() 實現這個功能,它返回一個它所讀到的字節的[]byte 數組及nil,或者其它錯誤,相似地ioutil.WriteFile則將一個[]byte 寫到一個文件裏去。函數

兩個函數的原型spa

func ReadFile(filename string) ([]byte, error) 
命令行

func WriteFile(filename string, data []byte, perm os.FileMode) error 
unix


package main


import (

    "fmt"

    "io/ioutil"

    "os"

)


func main() {

    inputFile := os.Args[1]

    outputFile := os.Args[2]

    buf, err := ioutil.ReadFile(inputFile)

    if err != nil {

        fmt.Fprintf(os.Stderr, "File Error: %s\n", err)

    }

    fmt.Printf("%s\n", string(buf))

    err = ioutil.WriteFile(outputFile, buf, 0x644)

    if err != nil {

        panic(err.Error())

    }


}

二、帶緩衝的讀文件,除了使用ReadString(),一些狀況下咱們並非一行行地讀文件或二進行文件,咱們能夠用bufio.Reader的Read()方法,方式以下指針

buf := make([]byte,1024)   //code

...

n,err := inputReader.Read(buf)

if(n==0){break} //n爲實際所讀到的byte數,當文件的字節數少於緩衝數組的長度時,會返回實際的字節數,

package main


import (

    "fmt"

    //"io/ioutil"

    "bufio"

    "os"

)


func main() {


    inputFile, inputError := os.Open(os.Args[1])

    if inputError != nil {

        fmt.Fprintf(os.Stderr, "File Error: %s\n", inputError)

    }

    fileReader := bufio.NewReader(inputFile)

    counter := 0

    for {

        buf := make([]byte, 1024)

        n, _ := fileReader.Read(buf)

        counter++

        //fmt.Printf("%d,%s", n, string(buf))

        if n == 0 {

            break

        }

        //fmt.Println(n, buf)


        fmt.Printf("%d,%s", n, string(buf))

        fmt.Printf("/////////////////\n")

    }

    fmt.Println(counter)

}


3 、從文件中讀列數據。若是文件是以空格分隔的列數據,則可使用fmt包裏的Fscan系列函數,下面的例子使用了這種方式,它將從列中的讀到的數據賦值到變量v1,v2和V3,而後追加到一個數組切片去。

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open(os.Args[1])
    if err != nil {
        panic(err)
    }
    var col1, col2, col3 []string
    for {
        var v1, v2, v3 string
        _, err := fmt.Fscanln(file, &v1, &v2, &v3)//Fscanln 將一次只讀一行,並將每列的數據賦值給相應的變量
        if err != nil {
            break
        }
        col1 = append(col1, v1)
        col2 = append(col2, v2)
        col3 = append(col3, v3)
    }
    fmt.Println(col1)
    fmt.Println(col2)
    fmt.Println(col3)
}


要讀的文件內容爲

a1 a2 a3

b1 b2 b3

c1 c2 c3

輸出爲

[a1 b1 c1]

[a2 b2 c2]

[a3 b3 c3]


備註: path包下有個子包filepath,它提供了些跨平臺的處理文件路徑及文件名的函數,例如filepath.Base(path)返回文件路徑的最後一個元素。

import "path/filepath"

filename := filepath.Base(path)

相關文章
相關標籤/搜索