Go を使用してファイルを読み書きする方法 質問する

Go を使用してファイルを読み書きする方法 質問する

私は独学で Go を学ぼうとしていますが、通常のファイルの読み取りと書き込みで行き詰まってしまいました。

までは取得できますが、読み取り関数が をパラメータとしてinFile, _ := os.Open(INFILE, 0, 0)受け取るため、実際にファイルの内容を取得しても意味がありません。[]byte

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

ベストアンサー1

Go でファイルを読み書きするすべての方法の Go 1 互換リストを作成しましょう。

ファイル 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.Openここでは、os.Createを囲む便利なラッパーである とを使用しましたos.OpenFile。通常は、 を直接呼び出す必要はありませんOpenFile

EOF の処理に注意してください。 は各呼び出しでRead入力を試みbufio.EOFその際にファイルの終わりに達するとエラーを返します。この場合、 はbufまだデータを保持します。 への後続の呼び出しは、Read読み取られたバイト数として 0 を返し、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(非推奨Go 1.16以降)。新しい方法については、この答え

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

とても簡単です! ただし、大きなファイルを扱っていないことが確実な場合にのみ使用してください。

おすすめ記事