From 85061bf84a36541d9390d9c2f374f5fc227e53f5 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Thu, 1 Nov 2012 21:01:25 -0700 Subject: [PATCH] publish reading-files --- examples.txt | 3 +- examples/reading-files/reading-files.go | 85 ++++++++++++++++++++++--- examples/reading-files/reading-files.sh | 9 +++ 3 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 examples/reading-files/reading-files.sh diff --git a/examples.txt b/examples.txt index 2efc77c..a129630 100644 --- a/examples.txt +++ b/examples.txt @@ -53,8 +53,9 @@ Number Parsing URL Parsing SHA1 Hashes Base64 Encoding -# Reading Files +Reading Files # Writing Files +# File Operations Line Filters Command-Line Arguments Command-Line Flags diff --git a/examples/reading-files/reading-files.go b/examples/reading-files/reading-files.go index beedb6c..59255bf 100644 --- a/examples/reading-files/reading-files.go +++ b/examples/reading-files/reading-files.go @@ -1,14 +1,83 @@ +// Reading and writing files are basic tasks needed for +// many Go programs. First we'll look at some examples of +// reading files. + package main -import "io/ioutil" -import "fmt" +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" +) -func main() { - contents, err := ioutil.ReadFile("xx-file-read.go") - if err != nil { - return +// Reading files requires checking most calls for errors. +// This helper will streamline our error checks below. +func check(e error) { + if e != nil { + panic(e) } - fmt.Print(string(contents)) } -// todo: streaming reads +func main() { + + // Perhaps the most basic file reading task is + // slurping a file's entire contents into memory. + dat, err := ioutil.ReadFile("/tmp/dat") + check(err) + fmt.Print(string(dat)) + + // You'll often want more control over how and what + // parts of a file are read. For these tasks, start + // by `Open`ing a file to obtain an `os.File` value. + f, err := os.Open("/tmp/dat") + + // Read some bytes from the beginning of the file. + // Allow up to 5 to be read but also not how many + // actually were read. + b1 := make([]byte, 5) + n1, err := f.Read(b1) + check(err) + fmt.Printf("%d bytes: %s\n", n1, string(b1)) + + // You can also `Seek` to a known location in the file + // and `Read` from there. + o2, err := f.Seek(6, 0) + check(err) + b2 := make([]byte, 2) + n2, err := f.Read(b2) + check(err) + fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2)) + + // The `io` package provides some functions that may + // be helpful for file reading. For example, reads + // like the ones above can be more robustly + // implemented with `ReadAtLeast`. + o3, err := f.Seek(6, 0) + check(err) + b3 := make([]byte, 2) + n3, err := io.ReadAtLeast(f, b3, 2) + check(err) + fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3)) + + // There is no built-in rewind, but `Seek(0, 0)` + // accomplishes this. + _, err = f.Seek(0, 0) + check(err) + + // The `bufio` package implements a buffered + // reader that may be useful both for it's efficiency + // with many small reads and because of the additional + // reading methods it provides. + r4 := bufio.NewReader(f) + b4, err := r4.Peek(5) + check(err) + fmt.Printf("5 bytes: %s\n", string(b4)) + + // Close the file when you're done (usually this would + // be scheduled immediately after `Open`ing with + // `defer`). + f.Close() + +} diff --git a/examples/reading-files/reading-files.sh b/examples/reading-files/reading-files.sh new file mode 100644 index 0000000..e34adca --- /dev/null +++ b/examples/reading-files/reading-files.sh @@ -0,0 +1,9 @@ +$ echo "hello" > /tmp/dat +$ echo "go" >> /tmp/dat +$ go run reading-files.go +hello +go +5 bytes: hello +2 bytes @ 6: go +2 bytes @ 6: go +5 bytes: hello