Goのファイル・ファイルライクオブジェクトもろもろ
ファイルの読み取り
Goでファイルを1行ずつ読み出したい場合はbufio.NewScannerを使うらしい。
そのNewScannerはio.Reader型の引数を取り、ファイルやファイルライクオブジェクトを渡す。
では、Goでファイルやファイルライクオブジェクトを扱う方法を調べてみた(以下3つ)。
Go | Python3 | |
---|---|---|
1 | strings.NewReader/bytes.NewReader | io.StringIO |
2 | ioutil.TempFile | tempfile.NamedTemporaryFile |
3 | os.Open | ビルトインのopen関数 |
1. strings.NewReader/bytes.NewReaderを使う方法 (PythonのStringIOに相当)
文字列をファイルのように扱うファイルライクオブジェクトとして、Goではstrings.NewReaderを使うらしい。
[追記: 2016/12/6]
stringを反復する場合はstrings.NewReader, byteを反復する場合はbytes.NewReaderと、2種類用意されている。
テキストファイルの代わりに使うならstrings.NewReaderが妥当。
x := bufio.NewScanner(strings.NewReader(text)) // または // x := bufio.NewScanner(bytes.NewReader([]byte(text))) for x.Scan() { fmt.Println(x.Text()) }
2. ioutil.TempFileを使う方法 (PythonのNamedTemporaryFileに相当)
Goにも一時ファイルをパァーッっと作ってくれるライブラリがあった。ioutil.TempFileがこれに当たる。
// import "io/ioutil" tmp, _ := ioutil.TempFile("", "_") tmp.Write([]byte("| わたしは\n")) tmp.Write([]byte("| い*がわ\n")) tmp.Write([]byte("| よ**と")) defer os.Remove(tmp.Name()) // PythonのNamedTemporaryFileと違い、ファイルの削除は自分でやる。 tmp.Seek(0, 0) x = bufio.NewScanner(tmp) for x.Scan() { fmt.Println(x.Text()) }
3. os.Openを使う方法 (Pythonのビルトインopen関数に相当)
普通にファイルを開くときは、os.Openを使う。
fp, _ := os.Open(tmp.Name()) defer fp.Close() x = bufio.NewScanner(fp) for x.Scan() { fmt.Println(x.Text()) }
まとめ
当然ながら、これらはすべてio.Reader型の変数に代入できる(以下)。
package main import ( "fmt" "io" "io/ioutil" "bufio" "bytes" "os" ) func main(){ var reader io.Reader var scanner *bufio.Scanner reader = bytes.NewReader([]byte("Hello, world.")) scanner = bufio.NewScanner(reader) fmt.Println(scanner) tmp, _ := ioutil.TempFile("", "_") defer os.Remove(tmp.Name()) tmp.Write([]byte("I have a pen.")) tmp.Seek(0, 0) reader = tmp scanner = bufio.NewScanner(reader) fmt.Println(scanner) fp, _ := os.Open(tmp.Name()) defer fp.Close() reader = fp scanner = bufio.NewScanner(reader) fmt.Println(scanner) }