Go

如何使用 Go 从文件读/写

发布于 2022-03-22 23:37:15

我一直在尝试自己学习 Go,但我一直在尝试读取和写入普通文件。

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

func (file *File) Read(b []byte) (n int, err Error)
关注者
0
被浏览
93
1 个回答
  • 面试哥
    面试哥 2022-03-22
    为面试而生,有面试问题,就找面试哥。

    让我们制作一个 Go 1 兼容的列表,列出在 Go 中读写文件的所有方式。

    因为文件 API 最近发生了变化,并且大多数其他答案不适用于 Go 1。他们也错过了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.Openos.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,用于轻松灵活地读写,同时它在后台处理缓冲。


    注意:以下代码适用于较旧的 Go 版本(Go 1.15 及之前)。事情变了。对于新的方式,看看这个答案

    使用 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)
        }
    }
    

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



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看