R 與 Java 整合範例

設定 R 調用 Java 執行環境

# R --vanilla CMD javareconf

Java interpreter : /usr/bin/java Java version : 1.7.0_25 Java home path : /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/jre Java compiler : /usr/bin/javac Java headers gen.: /usr/bin/javah Java archive tool: /usr/bin/jar trying to compile and link a JNI progam detected JNI cpp flags : -I$(JAVA_HOME)/../include -I$(JAVA_HOME)/../include/linux detected JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm gcc -std=gnu99 -I/usr/local/lib64/R/include -DNDEBUG -I/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/jre/../include -I/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/jre/../include/linux -I/usr/local/include -fpic -g -O2 -c conftest.c -o conftest.o gcc -std=gnu99 -shared -L/usr/local/lib64 -o conftest.so conftest.o -L/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/jre/lib/amd64/server -ljvm Java library path: $(JAVA_HOME)/lib/amd64/server JNI cpp flags : -I$(JAVA_HOME)/../include -I$(JAVA_HOME)/../include/linux JNI linker flags : -L$(JAVA_HOME)/lib/amd64/server -ljvm Updating Java configuration in /usr/local/lib64/R Done.

執行方式

    • 求算反矩陣 。

    • 透過 Java 屬性值 指定 GNU-R 執行檔 。

    • 透過命令列輸入陣列,[;] 為列分隔號,[,] 為行分隔號。

    • 以下為 Windows 批次檔內容:

SET RSCRIPT="C:\Program Files\R\R-2.14.2\bin\Rscript.exe" java -classpath dist\R-Matrix-Inverse.jar -DRscript=%RSCRIPT% com.emprogria.Run "1,0,-2;4,-2,1;1,2,-10"

執行主程式

package com.emprogria; import java.util.ArrayList; public class Run { public ArrayList rScript = null; RInverseMatrix rInverseMatrix = null; public void doTask(String arrayString) { this.rScript = new ArrayList<>(); this.rScript.clear(); this.rInverseMatrix = new RInverseMatrix(this.rScript); this.rInverseMatrix.getInverseMaxtrix(arrayString); } public static void main(String[] args) { Run rRun = new Run(); if (args.length == 0) { System.out.print("Matrix: "); try { java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); rRun.doTask(stdin.readLine()); } catch (java.io.IOException | NumberFormatException e) { System.err.println(e); } } else { rRun.doTask(args[0]); } } }

調用 GNU-R 程式

package com.emprogria; import java.io.*; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; public class RScript { private ArrayList rScript = null; public RScript(ArrayList rScript) { this.rScript = rScript; } private void writeScript(File scriptFile) throws IOException { BufferedWriter scriptROutput; scriptROutput = new BufferedWriter(new FileWriter(scriptFile)); for (int i = 0; i < this.rScript.size(); i++) { scriptROutput.write(this.rScript.get(i) + "\n"); } scriptROutput.close(); } public void runScript(String scriptFileName) { String commandLine = ""; if ((System.getProperty("Rscript") == null) && (System.getenv("RSCRIPT") == null)) { return; } try { File scriptFile = new File(scriptFileName + ".R"); this.writeScript(scriptFile); if (System.getenv("RSCRIPT") == null) { if (System.getProperty("Rscript") != null) { commandLine = System.getProperty("Rscript"); } } else { commandLine = System.getenv("RSCRIPT"); } commandLine += " \"" + scriptFile.getAbsolutePath() + "\""; Process R = Runtime.getRuntime().exec(commandLine); R.waitFor(); try (BufferedReader outputFromScript = new BufferedReader(new InputStreamReader(R.getInputStream()))) { String lineOutputScript = null; while ((lineOutputScript = outputFromScript.readLine()) != null) { System.out.println(lineOutputScript); } } scriptFile.delete(); } catch (InterruptedException | IOException ex) { Logger.getLogger(RInverseMatrix.class.getName()).log(Level.SEVERE, null, ex); } } @Override public String toString() { StringBuilder rScriptBuffer = new StringBuilder(); for (int i = 0; i < this.rScript.size(); i++) { rScriptBuffer.append(this.rScript.get(i)).append("\n"); } return rScriptBuffer.toString(); } public void addScriptLine(String newScriptLine) { this.rScript.add(newScriptLine); } public void addScriptLine(int lineNum, String newScriptLine) { this.rScript.add(lineNum, newScriptLine); } }

產生矩陣 GNU-R 程式

package com.emprogria; import java.util.ArrayList; public class RMatrix { private ArrayList rScript = new ArrayList<>(); private String varNameMatrix = "P"; public RMatrix() { } public RMatrix(String varNameMatrix) { this.varNameMatrix = varNameMatrix; } public ArrayList getScript() { return this.rScript; } public String formMatrixScript(String arrayString) { String[] arrayRowString = arrayString.split("[;]"); int row = arrayRowString.length, col = 0; for (int i = 0; i < row; i++) { String[] arrayColumnString = arrayRowString[i].split("[,]"); col = arrayColumnString.length; for (int j = 0; j < col; j++) { this.rScript.add(String.format("%s[%d, %d] <- %f", this.varNameMatrix, i + 1, j + 1, Double.parseDouble(arrayColumnString[j]))); } } this.rScript.add(0, String.format("%s <- array(0, c(%d, %d))", this.varNameMatrix, row, col)); return(this.toString()); } @Override public String toString() { StringBuilder rScriptBuffer = new StringBuilder(); for (int i = 0; i < this.rScript.size(); i++) { rScriptBuffer.append(this.rScript.get(i)).append("\n"); } return rScriptBuffer.toString(); } }

產生求算反矩陣 GNU-R 程式

package com.emprogria; import java.util.ArrayList; import java.util.UUID; public class RInverseMatrix { private ArrayList rScript = null; private RMatrix scriptMatrix = null; private RScript scriptEngine = null; public RInverseMatrix(ArrayList rScript) { this.rScript = rScript; this.scriptEngine = new RScript(this.rScript); this.scriptMatrix = new RMatrix(); } public void getInverseMaxtrix(String arrayString) { this.scriptEngine.addScriptLine(0, this.scriptMatrix.formMatrixScript(arrayString)); this.scriptEngine.addScriptLine("print(solve(P))"); this.scriptEngine.runScript(UUID.randomUUID().toString()); } }