【问题标题】:Calling Gnuplot in Swift在 Swift 中调用 Gnuplot
【发布时间】:2015-05-09 15:46:05
【问题描述】:

我正在尝试从 swift 调用 gunplot 以在 .png 中生成一些图。但是,下面的程序不起作用 --- 生成的 1.png 文件是空的。但是,如果我离开“set term aqua”,它会调用带有绘图的 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 和管道的新手,所以如果代码有问题或不推荐,请告诉我。

【问题讨论】:

  • 我不知道swift,但如果我是你,我可以尝试: 1. 在文件名"set output \"1.png\"\n" 之后添加换行符(你错过了\n) . 2:在 gnuplot 中关闭文件,在 "q\n" 之前添加类似 "set output \n " 的内容。让我知道它是否有效。
  • @Hastur 不,没有帮助。
  • 我希望...只要你修好了,我们就可以放一个 + :-) "set output \"1.png\"\n" +(我们错过了 +)。再次让我知道...
  • @Hastur 天哪!!而已! \n 和 + 不见了,它不起作用。我想你可以给出答案。

标签: swift gnuplot nstask nspipe


【解决方案1】:

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

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

我们的想法是创建一个字符串,就好像我们在gnuplot shell 中编写一样,所以对于每个\n,我们模拟一个新行,对于每个+,我们连接两个或多个字符串... 这甚至是 gnuplot 脚本...

的基本思想

通常使用gnuplot 编写外部脚本并加载它很舒服

  load "myscript.gnuplot"

或运行它

 gnuplot -persist myscript.gnuplot

通过这种方式,您将始终有可能在眨眼间重做绘图或分析,并且您的结果将始终可重现。

【讨论】:

    【解决方案2】:

    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
    
    """
    

    【讨论】:

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