The os
package (https://golang.org/pkg/os/) exposes the os.File
type which represents a file handle on the system. The os.File
type implements several IO primitives, including the io.Reader
and io.Writer
interfaces, which allows file content to be processed using the standard streaming IO API.
The os.Create
function creates a new file with the specified path. If the file already exists, os.Create
will overwrite it. The os.Open
function, on the other hand, opens an existing file for reading.
The following source snippet opens an existing file and creates a copy of its content using the io.Copy
function. One common, and recommended practice to notice is the deferred call to the method Close
on the file. This ensures a graceful release of OS resources when the function exits:
func main() { f1, err := os.Open("./file0.go") if err != nil { fmt.Println("Unable to open file:", err) os.Exit(1) } defer f1.Close() f2, err := os.Create("./file0.bkp") if err != nil { fmt.Println("Unable to create file:", err) os.Exit(1) } defer f2.Close() n, err := io.Copy(f2, f1) if err != nil { fmt.Println("Failed to copy:", err) os.Exit(1) } fmt.Printf("Copied %d bytes from %s to %s ", n, f1.Name(), f2.Name()) }
golang.fyi/ch10/file0.go
The os.OpenFile
function provides generic low-level functionalities to create a new file or open an existing file with fine-grained control over the file's behavior and its permission. Nevertheless, the os.Open
and os.Create
functions are usually used instead as they provide a simpler abstraction then the os.OpenFile
function.
The os.OpenFile
function take three parameters. The first one is the path of the file, the second parameter is a masked bit-field value to indicate the behavior of the operation (for example, read-only, read-write, truncate, and so on) and the last parameter is a posix-compliant permission value for the file.
The following abbreviated source snippet re-implements the file copy code, from earlier. This time, however, it uses the os.FileOpen
function to demonstrate how it works:
func main() { f1, err := os.OpenFile("./file0.go", os.O_RDONLY, 0666) if err != nil {...} defer f1.Close() f2, err := os.OpenFile("./file0.bkp", os.O_WRONLY, 0666) if err != nil {...} defer f2.Close() n, err := io.Copy(f2, f1) if err != nil {...} fmt.Printf("Copied %d bytes from %s to %s ", n, f1.Name(), f2.Name()) }
golang.fyi/ch10/file1.go
We have already seen how to use the os.Copy
function to move data into or out of a file. Sometimes, however, it will be necessary to have complete control over the logic that writes or reads file data. The following code snippet, for instance, uses the WriteString
method from the os.File
variable, fout,
to create a text file:
func main() { rows := []string{ "The quick brown fox", "jumps over the lazy dog", } fout, err := os.Create("./filewrite.data") if err != nil { fmt.Println(err) os.Exit(1) } defer fout.Close() for _, row := range rows { fout.WriteString(row) } }
golang.fyi/ch10/filewrite0.go
If, however, the source of your data is not text, you can write raw bytes directly to the file as shown in the following source snippet:
func main() { data := [][]byte{ []byte("The quick brown fox "), []byte("jumps over the lazy dog "), } fout, err := os.Create("./filewrite.data") if err != nil { ... } defer fout.Close() for _, out := range data { fout.Write(out) } }
golang.fyi/ch10/filewrite0.go
As an io.Reader
, reading from of the io.File
type directly can be done using the Read method. This gives access to the content of the file as a raw stream of byte slices. The following code snippet reads the content of file ../ch0r/dict.txt
as raw bytes assigned to slice p
up to 1024-byte chunks at a time:
func main() { fin, err := os.Open("../ch05/dict.txt") if err != nil { fmt.Println(err) os.Exit(1) } defer fin.Close() p := make([]byte, 1024) for { n, err := fin.Read(p) if err == io.EOF { break } fmt.Print(string(p[:n])) } }
golang.fyi/ch10/fileread.go
The os
package includes three pre-declared variables, os.Stdin
, os.Stdout
, and os.Stderr
, that represent file handles for standard input, output, and error of the OS respectively. The following snippet reads the file f1
and writes its content to io.Stdout
, standard output, using the os.Copy
function (standard input is covered later):
func main() { f1, err := os.Open("./file0.go") if err != nil { fmt.Println("Unable to open file:", err) os.Exit(1) } defer f1.Close() n, err := io.Copy(os.Stdout, f1) if err != nil { fmt.Println("Failed to copy:", err) os.Exit(1) } fmt.Printf("Copied %d bytes from %s ", n, f1.Name()) }
golang.fyi/ch10/osstd.go
3.142.114.19