私は独学で 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
入力を試みbuf
、io.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)
}
}
とても簡単です! ただし、大きなファイルを扱っていないことが確実な場合にのみ使用してください。