在Swift中调用Gnuplot

5
我试图从Swift中调用gunplot来生成一些.png格式的图形,但是下面的程序不起作用——生成的1.png文件为空。如果我去掉"set term aqua",它确实会调用窗口并展示图形。然而,当我尝试将输出设置为文件(png或pdf)时,结果总是一个空文件。
gnuplot的命令正确——我可以手动正常运行它们。
import Foundation

let task = NSTask()
task.launchPath = "/opt/local/bin/gnuplot"
task.currentDirectoryPath = "~"

let pipeIn = NSPipe()
task.standardInput = pipeIn
task.launch()

let plotCommand: NSString =
  "set term png\n" +
  "set output \"1.png\"\n"
  "plot sin(x)\n" +
  "q\n"

pipeIn.fileHandleForWriting.writeData(plotCommand.dataUsingEncoding(NSUTF8StringEncoding)!)

我对Swift和管道都很陌生,如果以下代码有任何错误或不建议使用的地方,请告诉我。


1
我不懂 swift,但如果我是你,我会尝试以下两种方法:1. 在文件名 "set output \"1.png\"\n" 后添加一个换行符(你漏了 __\n__)。2. 在 "q\n" 之前添加类似 "set output \n " 的内容来关闭 gnuplot 中的文件。请告诉我是否有效。 - Hastur
@Hastur 不,两者都没有帮助。 - Yrogirg
我希望你能修复一下这个问题,让我们甚至可以加上一个 + :) "set output \"1.png\"\n" + (我们错过了 +)。再次让我知道... - Hastur
@Hastur 哇!就是这样!\n和+都丢了,现在它工作了。我觉得你可以给个答案。 - Yrogirg
2个回答

4

当我们连接字符串时,很容易忽略一个简单的符号。
在这种情况下,您可以通过在带有set output的行中添加\n+来进行修复:

 "set output \"1.png\"\n" +

这个想法是创建一个字符串,就像我们在 gnuplot shell 中编写一样,因此每个\n模拟一个新行,每个+将两个或多个字符串连接起来...这甚至是gnuplot脚本的基本思路...
通常使用gnuplot编写外部脚本并加载它非常方便。
  load "myscript.gnuplot"

或者运行它

 gnuplot -persist myscript.gnuplot

这样做可以让你随时重新制作你的图表或分析,而且你的结果始终可以得到复现。


0

Swift 5.4

let commandString: String =
    """
    set terminal png
    set output 'FIND_ME_01.png'
    plot sin(x)
    quit\n
    """

func plot() {
    let argv: [String] = ["--persist"] // do not close interactive plot
    let task = Process()
    task.arguments = argv
    //                "/opt/homebrew/bin/gnuplot" // Big Sur, Apple Silicon
    task.launchPath = "/usr/local/bin/gnuplot"    // Big Sur, Intel
    // where to find the output
    let homeDir = FileManager.default.homeDirectoryForCurrentUser
    task.currentDirectoryURL = homeDir.appendingPathComponent("Desktop")


    let pipeIn = Pipe()
    task.standardInput = pipeIn
    let pipeOut = Pipe()
    task.standardOutput = pipeOut
    let pipeErr = Pipe()
    task.standardError = pipeErr
    
    do {
        try task.run()
        let commandData = commandString.data(using: .utf8)!
        pipeIn.fileHandleForWriting.write(commandData)
        
        let dataOut = pipeOut.fileHandleForReading.readDataToEndOfFile()
        if let output = String(data: dataOut, encoding: .utf8) {
            print("STANDARD OUTPUT\n" + output)
        }

        let dataErr = pipeErr.fileHandleForReading.readDataToEndOfFile()
        if let outputErr = String(data: dataErr, encoding: .utf8) {
            print("STANDARD ERROR \n" + outputErr)
        }
    } catch {
        print("FAILED: \(error)")
    }
    task.waitUntilExit()
    print("STATUS: \(task.terminationStatus)")
}

当前的Swift """ 语法允许使用多行字符串字面量。这避免了字符串连接的需要。

注意: commandString 需要以换行符终止。如果结尾没有使用 \n,则需要一个额外的空白行。

quit\n
"""

quit

"""

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接