ruk·si

🐹 Go
Files

Updated at 2014-02-02 14:48

Creating a file and writing to it. This is a bit low level so it is usually better to use bufio shown in the next example.

package main

import (
    "fmt"
    "os"
)

func main() {
    file, errCreate := os.Create("./test_create.txt")
    if errCreate != nil {
        panic(errCreate)
    }
    defer file.Close()

    byteCount1, errWrite := file.Write([]byte{115, 111, 109, 101, 10})
    if errWrite != nil {
        panic(errWrite)
    }
    fmt.Printf("wrote %d bytes\n", byteCount1)

    byteCount2, errWriteString := file.WriteString("writes\n")
    if errWriteString != nil {
        panic(errWriteString)
    }
    fmt.Printf("wrote %d bytes\n", byteCount2)

    // Sync forces the file contents to be written on the disk as they
    // might currently only be in the memory.
    errSync := file.Sync()
    if errSync != nil {
        panic(errSync)
    }
}

Reading with bufio.Writer. This is the way you should do it.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    // Create file if it does not exist, append if it exists.
    // Allow write and read for the owner and the group.
    file, errOpen := os.OpenFile("./buf.txt", os.O_CREATE|os.O_APPEND, 660)
    if errOpen != nil {
        panic(errOpen)
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    byteCount, errWrite := writer.WriteString("buffered\n")
    if errWrite != nil {
        panic(errWrite)
    }
    fmt.Printf("wrote %d bytes\n", byteCount)

    // Flush ensures that all buffered operations are applied.
    writer.Flush()
}

Reading a file with bufio.Reader. This can also be done using lower level functionality, but Reader interface provides so much more control with nonexistent performance loss.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func writeToFile(path string) {
    file, errOpen := os.OpenFile(path, os.O_CREATE|os.O_APPEND, 660)
    if errOpen != nil {
        panic(errOpen)
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    _, errWrite := writer.WriteString("salvation!\n")
    if errWrite != nil {
        panic(errWrite)
    }
    writer.Flush()
}

func readWholeFile(path string) {
    file, errOpen := os.Open(path)
    if errOpen != nil {
        panic(errOpen)
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    rawData := make([]byte, 1024)
    readByteCount, errRead := reader.Read(rawData)
    if errRead != nil {
        panic(errRead)
    }
    foundData := string(rawData[:readByteCount])
    fmt.Print(foundData)
}

func main() {
    writeToFile("./file_of_lightbringer.txt")
    readWholeFile("./file_of_lightbringer.txt")
}

Reading a file using bufio.Scanner. Scanner reads data from a file by splitting the data up by a character. By default, split character is newline \n.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func writeToFile(path string) {
    file, errOpen := os.OpenFile(path, os.O_CREATE|os.O_APPEND, 660)
    if errOpen != nil {
        panic(errOpen)
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    _, errWrite := writer.WriteString("madness and whatnot!\n")
    if errWrite != nil {
        panic(errWrite)
    }
    writer.Flush()
}

func readLineByLineWithScanner(path string) {
    file, errOpen := os.Open(path)
    if errOpen != nil {
        panic(errOpen)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    // scanner.Split(bufio.ScanWords) // To scan word by word.
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    if errScan := scanner.Err(); errScan != nil {
        panic(errScan)
    }
}

func main() {
    writeToFile("./file_of_smog.txt")
    readLineByLineWithScanner("./file_of_smog.txt")
}

Sources