【问题标题】:How to wrap exec.Command inside an io.Writer如何将 exec.Command 包装在 io.Writer 中
【发布时间】:2017-07-25 09:09:10
【问题描述】:

我正在尝试使用 mozjpeg 压缩 JPEG 图像。由于它没有官方的 go 绑定,我想我会调用它的 CLI 来进行压缩。

我尝试在compress/gzip 之后建模用法:

c := jpeg.NewCompresser(destFile)
_, err := io.Copy(c, srcFile)

现在的问题是,我如何将 CLI 封装在 Compresser 中以便支持这种用法?

我尝试过这样的事情:

type Compresser struct {
    cmd exec.Command
}

func NewCompressor(w io.Writer) *Compresser {
    cmd := exec.Command("jpegtran", "-copy", "none")
    cmd.Stdout = w
    c := &Compresser{cmd}
    return c
}

func (c *Compresser) Write(p []byte) (n int, err error) {
    if c.cmd.Process == nil {
        err = c.cmd.Start()
        if err != nil {
            return
        }
    }
    // How do I write p into c.cmd.Stdin?
}

但无法完成。

另外,第二个问题是,我什么时候关闭命令?如何关闭命令?

【问题讨论】:

    标签: image-processing go mozjpeg


    【解决方案1】:

    你应该看看Cmd.StdinPipe。文档中有一个示例,适合您的情况:

    package main
    
    import (
        "fmt"
        "io"
        "log"
        "os/exec"
    )
    
    func main() {
        cmd := exec.Command("cat")
        stdin, err := cmd.StdinPipe()
        if err != nil {
            log.Fatal(err)
        }
    
        go func() {
            defer stdin.Close()
            io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
        }()
    
        out, err := cmd.CombinedOutput()
        if err != nil {
            log.Fatal(err)
        }
    
        fmt.Printf("%s\n", out)
    }
    

    在这种情况下,CombinedOutput() 执行您的命令,并且执行完成,此时没有更多字节可从 out 读取。

    【讨论】:

      【解决方案2】:

      根据 Kiril 的回答,使用 cmd.StdInPipe 将您收到的数据传递给 Write

      但是,就关闭而言,我很想实现io.Closer。这将使*Compresser 自动实现io.WriteCloser 接口。

      我会使用Close() 作为没有更多数据要发送并且应该终止命令的通知。任何从命令返回的指示失败的非零退出代码都可以被捕获并作为错误返回。

      如果您的输入流很慢,我会警惕在Write() 中使用CombinedOutput()。该实用程序可以完成处理输入流并等待更多数据。这将被错误地检测为命令完成并导致无效输出。

      请记住,在 IO 操作期间,Write 方法可以被无限次调用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-16
        • 1970-01-01
        • 1970-01-01
        • 2017-07-22
        相关资源
        最近更新 更多