1. ホーム
  2. ファイル

[解決済み】Goでファイルの読み書きをする方法

2022-03-28 10:02:37

質問

独学でGoを勉強しているのですが、普通のファイルからの読み込みと書き込みにつまづいています。

までなら可能です。 inFile, _ := os.Open(INFILE, 0, 0) しかし、実際にファイルの内容を取得しても意味がありません。なぜなら、read 関数は []byte をパラメータとして使用します。

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

解決方法は?

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.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)
    }
}

楽勝です。ただし、大きなファイルを扱わないことが確実な場合のみ使用してください。