【问题标题】:ReadLine from io.ReadCloser来自 io.ReadCloser 的 ReadLine
【发布时间】:2012-10-25 08:55:22
【问题描述】:

我需要找到一种方法从 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 缓冲区。我尝试了两种方法。
1) nr, er := out.Read(buf) 其中buf 是一个字节数组。这里的问题是我需要为每个新行制动阵列
2)我的第二个选择是创建一个新的 bufio.reader
r := bufio.NewReader(out)
line,_,e := r.ReadLine()

如果我执行ls 之类的命令,它运行良好,我逐行获取输出,但是如果我执行 php 脚本,它会立即收到文件结束错误并退出(我猜这是因为延迟输出php)

编辑:我的问题是我在 go 例程中创建 bufio.Reader 而如果我像 minikomi 建议的那样在 StdoutPipe() 之后立即执行它,它工作正常

【问题讨论】:

  • 同时查看 exec.Wait,它会一直阻塞直到进程退出。
  • @minikomi 它在我的代码中,我将其包含在示例中并不重要,但感谢您的提示

标签: go


【解决方案1】:

您可以使用bufio创建一个阅读器,然后阅读到下一个换行符(注意,单引号表示字符!):

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

如果您试图在 goroutine 中读取阅读器,而没有任何东西可以停止脚本,它将退出。

【讨论】:

    【解决方案2】:

    另一个选项是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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多