320

私は自分でGoを学ぼうとしていましたが、通常のファイルからの読み取りと書き込みを試みることに困惑していました。

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

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

10 に答える 10

534

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

ファイルAPIが最近変更され、他のほとんどの回答がGo 1で機能しないためです。また、bufio重要なIMHOを見逃しています。

次の例では、ファイルから読み取り、宛先ファイルに書き込むことによってファイルをコピーします。

基本から始める

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を埋めようとし、そうすることでファイルの終わりに達するとエラーとして返されます。この場合でもデータは保持されます。結果としてのへの呼び出しは、読み取られたバイト数としてゼロを返し、エラーと同じです。その他のエラーはパニックにつながります。bufio.EOFbufReadio.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データとはあまり関係がないため、ここではバッファとして機能しているだけです。他のほとんどの状況(特にテキストファイルの場合)では、バックグラウンドでのバッファリングを処理しながら、簡単かつ柔軟に読み取りと書き込みを行うための優れたAPIbufioを提供することで非常に便利です。


注:次のコードは、古いバージョンの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)
    }
}

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

于 2012-03-16T15:17:18.610 に答える
54

これは良いバージョンです:

package main

import (
  "io/ioutil"; 
  )


func main() {
  contents,_ := ioutil.ReadFile("plikTekstowy.txt")
  println(string(contents))
  ioutil.WriteFile("filename", contents, 0644)
}
于 2010-04-11T18:10:38.173 に答える
34

使用するio.Copy

package main

import (
    "io"
    "log"
    "os"
)

func main () {
    // open files r and w
    r, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    defer r.Close()

    w, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    defer w.Close()

    // do the actual work
    n, err := io.Copy(w, r)
    if err != nil {
        panic(err)
    }
    log.Printf("Copied %v bytes\n", n)
}

車輪の再発明をしたくない場合は、io.Copyio.CopyNが役立つ可能性があります。io.Copy関数のソースを確認すると、Goライブラリにパッケージ化されているMostafaのソリューションの1つ(実際には「基本的な」ソリューション)にすぎません。しかし、彼らは彼よりもかなり大きなバッファーを使用しています。

于 2012-10-23T20:46:16.620 に答える
18

新しいバージョンのGoでは、ファイルの読み取り/書き込みが簡単です。ファイルから読み取るには:

package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    data, err := ioutil.ReadFile("text.txt")
    if err != nil {
        return
    }
    fmt.Println(string(data))
}

ファイルに書き込むには:

package main

import "os"

func main() {
    file, err := os.Create("text.txt")
    if err != nil {
        return
    }
    defer file.Close()

    file.WriteString("test\nhello")
}

これにより、ファイルの内容が上書きされます(ファイルがない場合は新しいファイルを作成します)。

于 2015-11-23T03:38:44.827 に答える
13

新しい方法

Go 1.16以降では、os.ReadFileを使用してファイルをメモリにロードし、を使用os.WriteFileしてメモリからファイルに書き込みます(ioutil.ReadFileは現在を呼び出しますos.ReadFile)。

os.ReadFileファイル全体がメモリに読み込まれるため、注意してください。

package main

import "os"

func main() {
    b, err := os.ReadFile("input.txt")
    if err != nil {
        log.Fatal(err)
    }

    // `b` contains everything your file does
    // This writes it to the Standard Out
    os.Stdout.Write(b)

    // You can also write it to a file as a whole
    err = os.WriteFile("destination.txt", b, 0644)
    if err != nil {
        log.Fatal(err)
    }
}
于 2021-01-30T16:38:06.387 に答える
10

[]byteバイト配列の全部または一部のスライス(サブストリングと同様)です。len()スライスは、システムが配列(スライス)のすべてまたは一部を見つけてアクセスするための非表示のポインターフィールドと、およびcap()関数を使用してアクセスできるスライスの長さと容量のフィールドを備えた値構造と考えてください。。

バイナリファイルを読み取って印刷する、実用的なスターターキットを次に示します。inNameシステム上の小さなファイルを参照するには、リテラル値を変更する必要があります。

package main
import (
    "fmt";
    "os";
)
func main()
{
    inName := "file-rw.bin";
    inPerm :=  0666;
    inFile, inErr := os.Open(inName, os.O_RDONLY, inPerm);
    if inErr == nil {
        inBufLen := 16;
        inBuf := make([]byte, inBufLen);
        n, inErr := inFile.Read(inBuf);
        for inErr == nil {
            fmt.Println(n, inBuf[0:n]);
            n, inErr = inFile.Read(inBuf);
        }
    }
    inErr = inFile.Close();
}
于 2009-11-30T23:44:07.760 に答える
7

これを試して:

package main

import (
  "io"; 
  )


func main() {
  contents,_ := io.ReadFile("filename");
  println(string(contents));
  io.WriteFile("filename", contents, 0644);
}
于 2009-11-30T20:14:40.227 に答える
3

fmtパッケージも使用できます。

package main

import "fmt"

func main(){
    file, err := os.Create("demo.txt")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    
    fmt.Fprint(file, name)
}
于 2021-08-15T14:54:32.093 に答える
1

ドキュメントを見るだけで、[] byte型のバッファを宣言し、それを読み取りに渡す必要があるようです。これにより、その数まで読み取り、実際に読み取られた文字数(およびエラー)が返されます。

ドキュメントは言う

読み取りは、ファイルから最大len(b)バイトを読み取ります。読み取られたバイト数と、存在する場合はエラーを返します。EOFは、errがEOFに設定されたゼロカウントによって通知されます。

それはうまくいきませんか?

編集:また、 osパッケージを使用する代わりに、 bufioパッケージで宣言されたリーダー/ライターインターフェイスを使用する必要があると思います。

于 2009-11-30T19:22:41.883 に答える
1

Readメソッドは、バイトパラメーターを受け取ります。これは、バイトパラメーターが読み込まれるバッファーであるためです。これは一部のサークルでは一般的なイディオムであり、考えてみると理にかなっています。

このようにして、リーダーによって読み取られるバイト数を決定し、戻り値を調べて実際に読み取られたバイト数を確認し、エラーを適切に処理できます。

他の人が彼らの答えで指摘しているように、bufioはおそらくあなたがほとんどのファイルから読みたいものです。

本当に便利なので、もう1つヒントを追加します。ファイルから行を読み取るには、ReadLineメソッドではなく、ReadBytesまたはReadStringメソッドを使用するのが最適です。

于 2012-03-19T03:24:54.843 に答える