2015-09-16 6 views
5

Ich habe ein Rscript in einer String-Variablen und ich möchte es aus dem Java-Programm ausführen und eine Variable an es übergeben. Wenn ich dieses R-Skript eigenständig ausführe, funktioniert es gut. Ich habe auf einer Linie, dass R Skript umgewandelt, indem es alles zu entkommen durch Python-Programm wie folgt:nicht in der Lage, R-Skript von Java-Programm auszuführen?

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 

Ich verwende die gedruckte Zeichenkette aus und speichern sie in String-Variable und dann mit Ich Ausführung Code unten und es funktioniert überhaupt nicht. Ich übergebe path und client_users Variable zu über R-Skript.

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); 
} 

Oben Code funktioniert gut mit Bash Shell-Skript. Gibt es etwas, das ich speziell für R-Skript machen muss? Ich werde den gleichen Code für Bash-Skript und R-Skripte verwenden.

Und das ist der Fehler Ich erhalte:

/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')' 

Und wenn ich commandList.add("/bin/bash"); entfernen und hinzufügen commandList.add("/bin/Rscript"); dann sehe ich unten Fehler:

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

Update: -

Anstatt mein oben beschriebenes Skript zu verwenden, entschied ich mich, das einfache Print-Hell-Skript in r zu verwenden, um zu sehen, ob ich es durchspielen kann ugh Java oder nicht.

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

Als ich dieses Skript mit commandList.add("/bin/bash"); ausführen, bekomme ich diesen Fehler:

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

Aber wenn ich mit diesem commandList.add("/bin/sh"); ausführen, bekomme ich diesen Fehler:

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

Antwort

3

Sie haben um /usr/bin/Rscript direkt zu laufen. Auch dann, wenn dieses Programm nicht Skripte von der Standardeingabe lesen (Sie müssen den Pfad zu dem Skript als Argument für Rscript angeben), so müssen Sie:

  • erstellen eine temporäre Datei
  • schreiben Ihr Skript
  • Führen Sie Ihren Skript mit Rscript
  • Ihrer temporären Datei (als guten Programmier) löschen

als ein Beispiel, das ist ein 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); 
} 

Als Alternative und wenn Ihr Skript einen „shebang“ als erste Zeile hat, können Sie diese Änderungen tun:

  • gesetzt sein ausführbares Attribut auf „true“
  • Einsatz Der Pfad zur temporären Datei als erstes Element in der Befehlsliste (i. e.löschen commandList.add("/usr/bin/Rscript");)

der Teil des Codes geändert werden, wäre:

... 

// 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); 

...