- 標準入力
package main import ( "os" "io" "fmt" ) func main() { for { buffer := make([]byte, 5) size, err := os.Stdin.Read(buffer) if err == io.EOF { fmt.Println("EOF") break } fmt.Printf("size=%d input='%s'\n", size, string(buffer)) } }
- ファイル入力
package main import ( "os" "io" ) func main() { file, err := os.Open("main.go") if err != nil { panic(err) } defer file.Close() io.Copy(os.Stdout, file) }
- ネットワーク通信の読み込み
package main import ( "net" "net/http" "bufio" "fmt" "io" "os" ) func main() { conn, err := net.Dial("tcp", "ascii.jp:80") if err != nil { panic(err) } conn.Write([]byte("GET / HTTP/1.0\r\nHost: ascii.jp\r\n\r\n")) res, err := http.ReadResponse(bufio.NewReader(conn), nil) fmt.Println(res.Header) defer res.Body.Close() io.Copy(os.Stdout, res.Body) }
- エンディアン変換
package main import ( "bytes" "encoding/binary" "fmt" ) func main() { data := []byte{0x0, 0x0, 0x27, 0x10} var i int32 binary.Read(bytes.NewReader(data), binary.BigEndian, &i) fmt.Printf("data: %d\n", i) }
- PNGファイルを分析してみる
package main import ( "io" "encoding/binary" "fmt" "os" ) func dumpChunk(chunk io.Reader) { var length int32 binary.Read(chunk, binary.BigEndian, &length) buffer := make([]byte, 4) chunk.Read(buffer) fmt.Printf("chunk, '%v' (%d bytes)\n", string(buffer), length) } func readChunks(file *os.File) []io.Reader { var chunks []io.Reader file.Seek(8, 0) var offset int64 = 8 for { var length int32 err := binary.Read(file, binary.BigEndian, &length) if err == io.EOF { break } chunks = append(chunks, io.NewSectionReader(file, offset, int64(length)+12)) offset, _ = file.Seek(int64(length+8), 1) } return chunks } func main() { file, err := os.Open("Lenna.png") if err != nil { panic(err) } defer file.Close() chunks := readChunks(file) for _, chunk := range chunks { dumpChunk(chunk) } }
実行結果
chunk, 'IHDR' (13 bytes) chunk, 'sRGB' (1 bytes) chunk, 'IDAT' (473761 bytes) chunk, 'IEND' (0 bytes) Process finished with exit code 0
- PNG画像に秘密のテキストを入れてみる
package main import ( "io" "bytes" "encoding/binary" "hash/crc32" "os" "fmt" ) func textChunk(text string) io.Reader { byteData := []byte(text) var buffer bytes.Buffer binary.Write(&buffer, binary.BigEndian, int32(len(byteData))) buffer.WriteString("tExt") buffer.Write(byteData) crc := crc32.NewIEEE() io.WriteString(crc, "tExt") binary.Write(&buffer, binary.BigEndian, crc.Sum32()) return &buffer } func readChunks(file *os.File) []io.Reader { var chunks []io.Reader file.Seek(8, 0) var offset int64 = 8 for { var length int32 err := binary.Read(file, binary.BigEndian, &length) if err != nil { break } chunks = append(chunks, io.NewSectionReader(file, offset, int64(length)+12)) offset , _ = file.Seek(int64(length+8), 1) } return chunks } func dumpChunk(chunk io.Reader) { var length int32 binary.Read(chunk, binary.BigEndian, &length) buffer := make([]byte, 4) chunk.Read(buffer) fmt.Printf("chunk '%v' (%d bytes\n", string(buffer), length) if bytes.Equal(buffer, []byte("tExt")) { rawText := make([]byte, length) chunk.Read(rawText) fmt.Println(string(rawText)) } } func writeFile() { file, err := os.Open("Lenna.png") if err != nil { panic(err) } defer file.Close() newFile, err := os.Create("Lenna2.png") if err != nil { panic(err) } chunks := readChunks(file) io.WriteString(newFile, "\x89PNG\r\n\x1a\n") io.Copy(newFile, chunks[0]) io.Copy(newFile, textChunk("ASCII PROGRAMMING++")) for _, chunk := range chunks[1:] { io.Copy(newFile, chunk) } } func readFile() { file, err := os.Open("Lenna2.png") if err != nil { panic(err) } defer file.Close() chunks := readChunks(file) for _, chunk := range chunks { dumpChunk(chunk) } } func main() { writeFile() readFile() }
- テキスト解析 改行/単語で区切る
package main import ( "bufio" "strings" "fmt" "io" ) var source = `1行目 2行目 3行目` func main() { reader :=bufio.NewReader(strings.NewReader(source)) for { line, err := reader.ReadString('\n') fmt.Printf("%#v\n", line) if err == io.EOF { break } } }
- bufio.Scannerを使う
package main import ( "bufio" "strings" "fmt" ) var source = `1行目 2行目 3行目` func main() { scanner := bufio.NewScanner(strings.NewReader(source)) for scanner.Scan() { fmt.Printf("%#v\n", scanner.Text()) } }
- データ型を指定して解析
package main import ( "strings" "fmt" ) var source = "123 1.234 1.0e4 test" func main() { reader := strings.NewReader(source) var i int var f, g float64 var s string fmt.Fscan(reader, &i, &f, &g, &s) fmt.Printf("i=%#v f=%#v g=%#v s=%#v\n", i, f, g, s) }
実行結果
i=123 f=1.234 g=10000 s="test"
Fscan
はスペース(または改行)で区切られたstringを読み込んで2つ目以降の引数の変数に代入していく。
- csvフォーマットの文字列の解析
package main import ( "strings" "encoding/csv" "io" "fmt" ) var csvSource = `13101, "100 ", "1000003", "トウキョウト", "チヨダク", "ヒトツバシ(1チョウメ)", "東京都", "千代田区", "一ツ橋(1丁目)", 1,0,1,0,0,0 13101, "101 ", "1000003", "トウキョウト", "チヨダク", "ヒトツバシ(2チョウメ)", "東京都", "千代田区", "一ツ橋(2丁目)", 1,0,1,0,0,0 13101, "100 ", "1000012", "トウキョウト", "チヨダク", "ヒビヤコウエン", "東京都", "千代田区", "日比谷公園", 0,0,0,0,0,0 13101, "102 ", "1000093", "トウキョウト", "チヨダク", "ヒトツバシ(1チョウメ)", "東京都", "千代田区", "平河町", 0,0,1,0,0,0 13101, "102 ", "1000071", "トウキョウト", "チヨダク", "ヒトツバシ(1チョウメ)", "東京都", "千代田区", "富士見", 0,0,1,0,0,0 ` func main() { reader := strings.NewReader(csvSource) csvReader := csv.NewReader(reader) csvReader.LazyQuotes = true for { line, err := csvReader.Read() if err == io.EOF { break } fmt.Println(line[2], line[6:9]) } }
実行結果
"1000003" [ "東京都" "千代田区" "一ツ橋(1丁目)"] "1000003" [ "東京都" "千代田区" "一ツ橋(2丁目)"] "1000012" [ "東京都" "千代田区" "日比谷公園"] "1000093" [ "東京都" "千代田区" "平河町"] "1000071" [ "東京都" "千代田区" "富士見"]
BOM付UTF-8にはまった。書籍そのままでは動かない。
GoでBOM付きのUTF8なCSVを扱うには | tail -f pinzo.log
encoding/csv: bare " in non-quoted-field · Issue #21672 · golang/go · GitHub
- io.Reader/io.Writerでストリームを自由に操る
package main import ( "bytes" "io" "os" ) func main() { header := bytes.NewBufferString(("----- HEADER -----\n")) content := bytes.NewBufferString("Example of io.MultiReader\n") footer := bytes.NewBufferString("----- FOOTER -----\n") reader := io.MultiReader(header, content, footer) io.Copy(os.Stdout, reader) }
package main import ( "bytes" "fmt" "io" "io/ioutil" ) func main() { var buffer bytes.Buffer reader := bytes.NewBufferString("Example of io.TeeReader\n") teeReader := io.TeeReader(reader, &buffer) _, _ = ioutil.ReadAll(teeReader) fmt.Println(buffer.String()) }