2011-05-26 10 views
8

¿Cuál es la forma idiomática de hacer una línea de lectura en Cadena en Go? las funciones en bruto proporcionadas en la biblioteca estándar parecen realmente de bajo nivel, devuelven matrices de bytes. ¿Hay alguna forma más fácil de obtener una cadena de una función de lectura?ir readline -> string

+1

posible duplicado de [lectura de archivo línea por línea en ir] (http://stackoverflow.com/questions/8757389/reading-file-line-by-line-in-go) – Malcolm

Respuesta

10

Estos son algunos ejemplos que usan bufio.ReadLine y 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) 
} 
+0

Gracias, estaba esperando un más construido en forma de hacer esto. Me sorprende que esta funcionalidad no esté incorporada. – jz87

+8

Si está viendo esto hoy, querrá usar io.EOF en lugar de os.EOF. – oleks

+0

... y 'errors.New (...)' en lugar de 'os.NewError (...)' y 'NewReaderSize()' solo devuelve un argumento. – topskip

11

Escribí una forma de leer fácilmente cada línea de un archivo. La función Readln (* bufio.Reader) devuelve una línea (sans \ n) de la estructura subyacente bufio.Reader.

// 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 
} 

Puede leer Readln para leer cada línea de un archivo. El siguiente código lee cada línea en un archivo y genera cada línea en 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) 
} 

¡Salud!

+4

esto es genial, pero usar append es muy malo. si cambia esa línea para copiar (ln, línea), la función se ejecutará unas 20 veces más rápido. Esto era imprescindible para mí ya que estoy analizando archivos que son muchos GB. – mschuett

+2

@mschuett ¿puedes compartir el código modificado con copia? –

Cuestiones relacionadas