Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang, is there a better way read a file of integers into an array?

Tags:

go

I need to read a file of integers into an array. I have it working with this:

package main

import (
    "fmt"
    "io"
    "os"
)

func readFile(filePath string) (numbers []int) {
    fd, err := os.Open(filePath)
    if err != nil {
        panic(fmt.Sprintf("open %s: %v", filePath, err))
    }
    var line int
    for {

        _, err := fmt.Fscanf(fd, "%d\n", &line)

        if err != nil {
            fmt.Println(err)
            if err == io.EOF {
                return
            }
            panic(fmt.Sprintf("Scan Failed %s: %v", filePath, err))

        }
        numbers = append(numbers, line)
    }
    return
}

func main() {
    numbers := readFile("numbers.txt")
    fmt.Println(len(numbers))
}

The file numbers.txt is just:

1
2
3
...

ReadFile() seems too long (maybe because of the error handing).

Is there a shorter / more Go idiomatic way to load a file?

like image 874
Lance Rushing Avatar asked Mar 25 '12 17:03

Lance Rushing


People also ask

How to read text file in golang?

The simplest way of reading a text or binary file in Go is to use the ReadFile() function from the os package. This function reads the entire content of the file into a byte slice, so you should be careful when trying to read a large file - in this case, you should read the file line by line or in chunks.

How to read and write a file in golang?

Golang offers a vast inbuilt library that can be used to perform read and write operations on files. In order to read from files on the local system, the io/ioutil module is put to use. The io/ioutil module is also used to write content to the file.

What does an array index or element do?

An array is an object that stores many values of the same type. An array element is one value in an array. An array index is an integer indicating a position in an array. Like Strings, arrays use zero-based indexing, that is, array indexes start with 0.


2 Answers

I would do it like this:

package main

import (
"fmt"
    "io/ioutil"
    "strconv"
    "strings"
)

// It would be better for such a function to return error, instead of handling
// it on their own.
func readFile(fname string) (nums []int, err error) {
    b, err := ioutil.ReadFile(fname)
    if err != nil { return nil, err }

    lines := strings.Split(string(b), "\n")
    // Assign cap to avoid resize on every append.
    nums = make([]int, 0, len(lines))

    for _, l := range lines {
        // Empty line occurs at the end of the file when we use Split.
        if len(l) == 0 { continue }
        // Atoi better suits the job when we know exactly what we're dealing
        // with. Scanf is the more general option.
        n, err := strconv.Atoi(l)
        if err != nil { return nil, err }
        nums = append(nums, n)
    }

    return nums, nil
}

func main() {
    nums, err := readFile("numbers.txt")
    if err != nil { panic(err) }
    fmt.Println(len(nums))
}
like image 35
Mostafa Avatar answered Oct 11 '22 10:10

Mostafa


Using a bufio.Scanner makes things nice. I've also used an io.Reader rather than taking a filename. Often that's a good technique, since it allows the code to be used on any file-like object and not just a file on disk. Here it's "reading" from a string.

package main

import (
    "bufio"
    "fmt"
    "io"
    "strconv"
    "strings"
)

// ReadInts reads whitespace-separated ints from r. If there's an error, it
// returns the ints successfully read so far as well as the error value.
func ReadInts(r io.Reader) ([]int, error) {
    scanner := bufio.NewScanner(r)
    scanner.Split(bufio.ScanWords)
    var result []int
    for scanner.Scan() {
        x, err := strconv.Atoi(scanner.Text())
        if err != nil {
            return result, err
        }
        result = append(result, x)
    }
    return result, scanner.Err()
}

func main() {
    tf := "1\n2\n3\n4\n5\n6"
    ints, err := ReadInts(strings.NewReader(tf))
    fmt.Println(ints, err)
}
like image 191
Paul Hankin Avatar answered Oct 11 '22 12:10

Paul Hankin