What is the idiomatic way to do a readline to string in Go? the raw functions provided in the standard library seem really low level, they return byte arrays. Is there any built in easier way to get a string out of a readline function?
Asked
Active
Viewed 2.8k times
3 Answers
16
I wrote up a way to easily read each line from a file. The Readln(*bufio.Reader) function returns a line (sans \n) from the underlying bufio.Reader struct.
// Readln returns a single line (without the ending \n)
// from the input buffered reader.
// An error is returned iff there is an error with the
// buffered reader.
func Readln(r *bufio.Reader) (string, error) {
var (isPrefix bool = true
err error = nil
line, ln []byte
)
for isPrefix && err == nil {
line, isPrefix, err = r.ReadLine()
ln = append(ln, line...)
}
return string(ln),err
}
You can use Readln to read every line from a file. The following code reads every line in a file and outputs each line to stdout.
f, err := os.Open(fi)
if err != nil {
fmt.Println("error opening file= ",err)
os.Exit(1)
}
r := bufio.NewReader(f)
s, e := Readln(r)
for e == nil {
fmt.Println(s)
s,e = Readln(r)
}
Cheers!

Malcolm
- 2,394
- 1
- 23
- 26
-
4this is great but using append is very bad. if you switch that line to copy(ln, line) the function will run about 20 times faster. This was a must for me since I'm parsing files that are many GB. – michael.schuett May 05 '15 at 05:45
-
5
14
Here's are some examples using bufio.ReadLine and bufio.ReadString.
package main
import (
"bufio"
"fmt"
"os"
)
func ReadLine(filename string) {
f, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
r := bufio.NewReaderSize(f, 4*1024)
line, isPrefix, err := r.ReadLine()
for err == nil && !isPrefix {
s := string(line)
fmt.Println(s)
line, isPrefix, err = r.ReadLine()
}
if isPrefix {
fmt.Println("buffer size to small")
return
}
if err != io.EOF {
fmt.Println(err)
return
}
}
func ReadString(filename string) {
f, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
r := bufio.NewReader(f)
line, err := r.ReadString('\n')
for err == nil {
fmt.Print(line)
line, err = r.ReadString('\n')
}
if err != io.EOF {
fmt.Println(err)
return
}
}
func main() {
filename := `testfile`
ReadLine(filename)
ReadString(filename)
}
-
Thanks, I was hoping for a more built in way to do this. I'm surprised this functionality is not built in. – jz87 May 28 '11 at 04:04
-
8If you're looking at this today, you'll want to use io.EOF in place of os.EOF. – oleks Jul 16 '12 at 08:44
-
... and `errors.New(...)` instead of `os.NewError(...)` and `NewReaderSize()` returns only one argument. – topskip Aug 17 '12 at 19:54
-
@jz87the purpose of go is to give you the ability to build tools. If that functionality was built in... also other 3.000.000.000 stuff needed to be there. The point is... if you can build it using go... why it would be there in the first place? – Pedro Luz Apr 06 '16 at 19:29
-
3
0
You can also use bufio.NewScanner
:
package main
import (
"bufio"
"os"
)
func main() {
f, e := os.Open("file.txt")
if e != nil {
panic(e)
}
defer f.Close()
s := bufio.NewScanner(f)
for s.Scan() {
println(s.Text())
}
}