无法从java程序执行R脚本?

我在String变量中有一个Rscript,我想从Java程序执行它并将一些变量传递给它。 如果我独立执行该R脚本,它可以正常工作。 我已经通过使用Python程序将其转换为一行来将R脚本转换为一行,如下所示:

import json jsonstr = json.dumps({"script": """\ #!/usr/bin/Rscript # read the data file library('jsonlite') library('rpart') args <- as.list(Sys.getenv(c( "path", "client_users"))) if (args[["path"]]==""){ args[["path"]] <- "." } # other stuff here # other stuff here """}) print jsonstr 

我使用打印出来的字符串并将其存储在String变量中,然后我执行下面的代码,它根本不起作用。 我将pathclient_users变量传递给上面的R脚本。

 public static void main(String[] args) throws IOException, InterruptedException { // this is your script in a string // String script = "#!/bin/bash\n\necho \"Hello World\"\n\n readonly PARAM1=$param1\n echo $PARAM1\n\nreadonly PARAM2=$param2\n echo $PARAM2\n\n"; String script = "above R Script here"; List commandList = new ArrayList(); commandList.add("/bin/bash"); ProcessBuilder builder = new ProcessBuilder(commandList); builder.environment().put("path", "/home/david"); builder.environment().put("client_users", "1000"); builder.redirectErrorStream(true); Process shell = builder.start(); // Send your script to the input of the shell, something // like doing cat script.sh | bash in the terminal try(OutputStream commands = shell.getOutputStream()) { commands.write(script.getBytes()); } // read the outcome try(BufferedReader reader = new BufferedReader(new InputStreamReader(shell.getInputStream()))) { String line; while((line = reader.readLine()) != null) { System.out.println(line); } } // check the exit code int exitCode = shell.waitFor(); System.out.println("EXIT CODE: " + exitCode); } 

上面的代码适用于bash shell脚本。 我需要为R脚本做些什么特别的事吗? 我将对bash脚本和R脚本使用相同的代码。

这是我得到的错误:

 /bin/bash: line 7: -: No such file or directory /bin/bash: line 10: syntax error near unexpected token `'jsonlite'' /bin/bash: line 10: `library('jsonlite')' 

如果我删除commandList.add("/bin/bash"); 并添加commandList.add("/bin/Rscript"); 然后我看到下面的错误:

 Cannot run program "/bin/Rscript": error=2, No such file or directory 

更新: –

我没有使用上面的脚本,而是决定在r中使用简单的打印地狱脚本来查看是否可以通过Java执行它。

 // this will print hello String script = "#!/usr/bin/env Rscript\nsayHello <- function(){\n print('hello')\n}\n\nsayHello()\n"; 

当我用commandList.add("/bin/bash");执行这个脚本时commandList.add("/bin/bash"); ,我收到此错误:

 /bin/bash: line 2: syntax error near unexpected token `(' /bin/bash: line 2: `sayHello <- function(){' 

但是如果我用这个commandList.add("/bin/sh"); ,我收到此错误:

 /bin/sh: 2: Syntax error: "(" unexpected 

您必须直接运行/usr/bin/Rscript 。 此外,此程序不读取标准输入中的脚本(您必须指定脚本的路径作为Rscript的参数),因此您必须:

  • 创建临时文件
  • 写你的脚本
  • 使用Rscript执行脚本
  • 删除你的临时文件(作为一个很好的编程实践)

例如,这是一个POC:

 public static void main(String[] args) throws IOException, InterruptedException { // Your script String script = "#!/usr/bin/env Rscript\n" + "\n" + "sayHello <- function() {\n" + " print('hello')\n" + "}\n" + "\n" + "sayHello()\n"; // create a temp file and write your script to it File tempScript = File.createTempFile("test_r_scripts_", ""); try(OutputStream output = new FileOutputStream(tempScript)) { output.write(script.getBytes()); } // build the process object and start it List commandList = new ArrayList<>(); commandList.add("/usr/bin/Rscript"); commandList.add(tempScript.getAbsolutePath()); ProcessBuilder builder = new ProcessBuilder(commandList); builder.redirectErrorStream(true); Process shell = builder.start(); // read the output and show it try(BufferedReader reader = new BufferedReader( new InputStreamReader(shell.getInputStream()))) { String line; while((line = reader.readLine()) != null) { System.out.println(line); } } // wait for the process to finish int exitCode = shell.waitFor(); // delete your temp file tempScript.delete(); // check the exit code (exit code = 0 usually means "executed ok") System.out.println("EXIT CODE: " + exitCode); } 

作为替代方案, 如果您的脚本有一个“shebang”作为第一行 ,您可以执行以下更改:

  • 将其可执行属性设置为“true”
  • 使用临时文件的路径作为commandList中的第一个元素(即删除commandList.add("/usr/bin/Rscript");

要修改的代码部分是:

 ... // create a temp file and write your script to it File tempScript = File.createTempFile("test_r_scripts_", ""); tempScript.setExecutable(true); try(OutputStream output = new FileOutputStream(tempScript)) { output.write(script.getBytes()); } // build the process object and start it List commandList = new ArrayList<>(); commandList.add(tempScript.getAbsolutePath()); ProcessBuilder builder = new ProcessBuilder(commandList); ...