2015-09-16 16 views
5

我在一個String變量中有一個Rscript,我想從Java程序執行它,並將一些變量傳遞給它。如果我獨立執行該R腳本,它可以正常工作。我已經轉換的R腳本於一行通過轉義它通過使用Python程序一切,如下所示:無法從java程序執行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 

我用印刷串出,並將其存儲在字符串變量,然後我正在與下面的代碼執行,並根本不起作用。我正在將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<String> 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");,我得到這個錯誤:

/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 

回答

3

您將有直接運行/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<String> 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); 
} 

作爲替代,如果你的腳本有一個「認領」作爲一線,你可以做這些改變:

  • 設置它的可執行文件的屬性爲「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<String> commandList = new ArrayList<>(); 
commandList.add(tempScript.getAbsolutePath()); 
ProcessBuilder builder = new ProcessBuilder(commandList); 

...