小编典典

如何使用Go从文件读/写文件?

go

我一直在尝试自己学习Go,但是在尝试读取和写入普通文件时遇到了麻烦。

我可以说到最远inFile, _ := os.Open(INFILE, 0, 0),但是实际上获取文件的内容没有任何意义,因为read函数将a
[]byte作为参数。

func (file *File) Read(b []byte) (n int, err Error)

阅读 331

收藏
2020-07-02

共1个答案

小编典典

让我们列出与Go 1兼容的清单,其中列出了在Go中读写文件的所有方式。

由于文件API最近已更改,并且大多数其他答案不适用于Go1。他们也错过了bufio重要的恕我直言。

在以下示例中,我通过读取文件并将其写入目标文件来复制文件。

从基础开始

package main

import (
    "io"
    "os"
)

func main() {
    // open input file
    fi, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    // close fi on exit and check for its returned error
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()

    // open output file
    fo, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    // close fo on exit and check for its returned error
    defer func() {
        if err := fo.Close(); err != nil {
            panic(err)
        }
    }()

    // make a buffer to keep chunks that are read
    buf := make([]byte, 1024)
    for {
        // read a chunk
        n, err := fi.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }

        // write a chunk
        if _, err := fo.Write(buf[:n]); err != nil {
            panic(err)
        }
    }
}

在这里,我使用了,os.Open并且os.Create它们是方便的包装器os.OpenFile。我们通常不需要OpenFile直接致电。

注意处理EOF。Read尝试填充buf每个调用,并io.EOF在到达文件末尾时返回错误。在这种情况下buf仍将保留数据。随之而来的调用Read返回零作为读取的字节数,并且与io.EOF错误相同。任何其他错误都会导致恐慌。

使用bufio

package main

import (
    "bufio"
    "io"
    "os"
)

func main() {
    // open input file
    fi, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    // close fi on exit and check for its returned error
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()
    // make a read buffer
    r := bufio.NewReader(fi)

    // open output file
    fo, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    // close fo on exit and check for its returned error
    defer func() {
        if err := fo.Close(); err != nil {
            panic(err)
        }
    }()
    // make a write buffer
    w := bufio.NewWriter(fo)

    // make a buffer to keep chunks that are read
    buf := make([]byte, 1024)
    for {
        // read a chunk
        n, err := r.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }

        // write a chunk
        if _, err := w.Write(buf[:n]); err != nil {
            panic(err)
        }
    }

    if err = w.Flush(); err != nil {
        panic(err)
    }
}

bufio在这里只是充当缓冲区,因为我们与数据无关。在大多数其他情况下(尤其是文本文件),bufio它为我们提供了一个很好的API,可轻松灵活地进行读写,同时还可以处理后台缓冲,因此非常有用。

使用ioutil

package main

import (
    "io/ioutil"
)

func main() {
    // read the whole file at once
    b, err := ioutil.ReadFile("input.txt")
    if err != nil {
        panic(err)
    }

    // write the whole body at once
    err = ioutil.WriteFile("output.txt", b, 0644)
    if err != nil {
        panic(err)
    }
}

非常简单!但是,只有在确定不处理大文件时才使用它。

2020-07-02