Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReadLine from io.ReadCloser

Tags:

go

I need to find a way to read a line from a io.ReadCloser object OR find a way to split a byte array on a "end line" symbol. However I don't know the end line symbol and I can't find it.

My application execs a php script and needs to get the live output from the script and do "something" with it when it gets it.

Here's a small piece of my code:

cmd := exec.Command(prog, args)   
/* cmd := exec.Command("ls")*/
out, err := cmd.StdoutPipe()
if err != nil {
  fmt.Println(err)
}
err = cmd.Start()
if err != nil {
  fmt.Println(err)
}

after this I monitor the out buffer in a go routine. I've tried 2 ways.
1) nr, er := out.Read(buf) where buf is a byte array. the problem here is that I need to brake the array for each new line
2) my second option is to create a new bufio.reader
r := bufio.NewReader(out)
line,_,e := r.ReadLine()

it runs fine if I exec a command like ls, I get the output line by line, but if I exec a php script it immediately get an End Of File error and exits(I'm guessing that's because of the delayed output from php)

EDIT: My problem was I was creating the bufio.Reader inside the go routine whereas if I do it right after the StdoutPipe() like minikomi suggested, it works fine

like image 456
Flame Avatar asked Oct 25 '12 08:10

Flame


1 Answers

You can create a reader using bufio, and then read until the next line break character (Note, single quotes to denote character!):

stdout, err := cmd.StdoutPipe()
rd := bufio.NewReader(stdout)
if err := cmd.Start(); err != nil {
    log.Fatal("Buffer Error:", err)
}

for {
    str, err := rd.ReadString('\n')
    if err != nil {
        log.Fatal("Read Error:", err)
        return
    }
    fmt.Println(str)
}

If you're trying to read from the reader in a goroutine with nothing to stop the script, it will exit.

like image 73
minikomi Avatar answered Sep 20 '22 04:09

minikomi