英文:
ReadLine from io.ReadCloser
问题
我需要找到一种方法从io.ReadCloser对象中读取一行,或者找到一种方法在一个字节数组上分割一个“结束行”符号。然而,我不知道结束行符号在哪里,也找不到它。
我的应用程序执行一个php脚本,并且需要获取脚本的实时输出,并在获取到输出时对其进行处理。
这是我的代码的一小部分:
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)
}
之后,我在一个go例程中监视out
缓冲区。我尝试了两种方法。
nr, er := out.Read(buf)
,其中buf
是一个字节数组。问题在于我需要在每个新行处分割数组。- 我的第二个选择是创建一个新的bufio.reader
r := bufio.NewReader(out) line,_,e := r.ReadLine()
如果我执行像ls
这样的命令,它可以正常运行,我逐行获取输出,但是如果我执行一个php脚本,它会立即出现文件结束错误并退出(我猜这是由于php的延迟输出导致的)。
编辑:我的问题是我在go例程中创建了bufio.Reader,而如果我像minikomi建议的那样在StdoutPipe()
之后立即创建它,它就可以正常工作。
英文:
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.
nr, er := out.Read(buf)
wherebuf
is a byte array. the problem here is that I need to brake the array for each new line- 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 likels
, 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
答案1
得分: 11
您可以使用bufio创建一个读取器,然后读取直到下一个换行符(注意,单引号表示字符!):
stdout, err := cmd.StdoutPipe()
rd := bufio.NewReader(stdout)
if err := cmd.Start(); err != nil {
log.Fatal("缓冲错误:", err)
}
for {
str, err := rd.ReadString('\n')
if err != nil {
log.Fatal("读取错误:", err)
return
}
fmt.Println(str)
}
如果您尝试在goroutine中从读取器中读取而没有任何停止脚本的内容,它将退出。
英文:
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.
答案2
得分: 3
另一个选项是bufio.NewScanner
:
package main
import (
"bufio"
"os/exec"
)
func main() {
cmd := exec.Command("go", "env")
out, err := cmd.StdoutPipe()
if err != nil {
panic(err)
}
buf := bufio.NewScanner(out)
cmd.Start()
defer cmd.Wait()
for buf.Scan() {
println(buf.Text())
}
}
https://golang.org/pkg/bufio#NewScanner
英文:
Another option is bufio.NewScanner
:
package main
import (
"bufio"
"os/exec"
)
func main() {
cmd := exec.Command("go", "env")
out, err := cmd.StdoutPipe()
if err != nil {
panic(err)
}
buf := bufio.NewScanner(out)
cmd.Start()
defer cmd.Wait()
for buf.Scan() {
println(buf.Text())
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论