Goでのファイルの読み込みを調べた
はじめに
Goでファイルの読み込みには以下のような選択肢があります。
-
os
パッケージを使用して、バイト単位で読み込む。 -
bufio
パッケージを使用して、行単位で読み込む。 -
io/ioutil
パッケージを使用して、一括で読み込む。(Go 1.16では非推奨) -
os
パッケージを使用して、一括で読み込む。(Go 1.16で使用できる)
これらの違いを自分なりにまとめ、備忘録として残します。
この記事が他の人の参考になれば幸いです。
また、この記事の内容に間違った記載がありましたら、指摘していただけるとありがたいです。
以下の例で読み込むファイル名はexample.txt
であり、
内容は以下のようになっています。
example.txt
123456789
aiueo
あいうえお
環境
名前 | バージョン |
---|---|
macOS Big Sur | 11.2.1 |
Go | 1.15.8 |
osパッケージでバイト単位で読み込む
os
パッケージのRead
メソッドを使用して、バイト単位で読み込みます。
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
contents := ""
f, err := os.Open("tmp/example.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
b := make([]byte, 12)
for {
n, err := f.Read(b)
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
contents += string(b[:n])
}
fmt.Println(contents)
}
出力
example.txt
123456789
aiueo
あいうえお
Open
関数で読み込み専用でファイルを開きます。
重要なのはb := make([]byte, 12)
のコードであり、要素数12のバイトのスライスを宣言しています。
このバイトのにf.Read
メソッドで読み込んだ内容が書き込まれます。
つまり、この例の場合は、ファイルを12バイトずつ読み込んでいます。そしてファイルの最後まで読み込むと停止します。
f.Read
関数の戻り値n
はバイトのスライスに新しく書き込んだバイト数です。
なお、一度に読み込むバイト数を大きくすれば、一括で読み込むこともできます。
bufioパッケージで行単位で読み込む
bufio
パッケージのText
メソッドを使用して、行単位で読み込みます。
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
contents := ""
f, err := os.Open("example.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
contents += scanner.Text()
fmt.Println(contents)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
fmt.Println("RESULT: ", contents)
}
出力
example.txt
example.txt
example.txt123456789
example.txt123456789aiueo
example.txt123456789aiueoあいうえお
RESULT: example.txt123456789aiueoあいうえお
ファイルをOpen
関数で開き、構造体File
のポインタを取得します。
NewScanner
関数で新しい構造体Scanner
のポインタを作成し、取得します。
Scan
メソッドは、Text
メソッドで文字列を取得するために、次のトークンまで読み込めるかをチェックします。読み込めない場合にはfalse
を返します。
Text
メソッドは、スキャンしたところまで読み込み、文字列を戻り値として返します。
bufio
パッケージには他にも色々な区切りで読み込めるメソッドがたくさんあるので気になったら調べて見ると良いです。
io/ioutilパッケージで一括で読み込む
io/ioutil
パッケージのReadFile
関数を用いて、一括で読み込みます。
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
b, err := ioutil.ReadFile("example.txt")
if err != nil {
log.Fatal(err)
}
contents := string(b)
fmt.Println(contents)
}
出力
example.txt
123456789
aiueo
あいうえお
ファイルパスを明示的に開く必要がなく、一番簡潔に記述することができます。
ReadFile
関数はファイル名を引数に取り、ファイルの中身をバイトのスライスで返します。
(Go 1.16より)osパッケージで一括で読み込む
上のソースコードでioutil
をos
に変えるだけです。
Go 1.16ではio/ioutil
パッケージが非推奨になり、その関数はos
パッケージもしくはio
パッケージで利用できます。