JAVA呼叫R語言
1 簡介
R是統計計算的強大工具,而JAVA是做應用系統的主流語言,兩者天然具有整合的需要。關於整合,一方面,R中可以建立JAVA物件呼叫JAVA方法,另一方面,JAVA中可以轉換R的資料型別呼叫R的函式,互相取長補短。現在也有一個專案JGR,用JAVA做R的圖形介面,可以實現高亮顯示自動補全等,還能讓JAVA和R互相呼叫。
關於R中呼叫JAVA,我想主要是為了利用其面向物件的特性,畢竟R語言近來很致力於向面向物件發展,有個很好的專案rJava可以實現,在www.rforge.net/rJava上。R中調JAVA對我似乎意義不大,本文主要介紹JAVA中呼叫R。
JAVA很適合開發應用系統,但是數學建模和計算能力非其所長,如果該系統需要進行大量的統計或者優化的計算,呼叫R是一種很好的方式。JAVA負責系統的構建,R用來做運算引擎,從而實現應用型和分析性相結合的系統。
目前網上有兩種方式使用java呼叫R。
2 Rserve的方式
2.1 介紹
首先要介紹的是Rserve的方式,這是一個基於TCP/IP的伺服器,通過二進位制協議傳輸資料,可以提供遠端連線,使得客戶端語言能夠呼叫R。目前Rserve作為一個package釋出在CRAN上,可以直接使用install.packages("Rserve")進行安裝。需要使用時在R控制檯下載入該包,然後輸入命令Rserve(),開啟伺服器,就可以供客戶端呼叫。
其客戶端可以有多種,這裡只介紹JAVA客戶端。最早的客戶端包是JRclient,在www.rosuda.org/Rserve上還可以下載到,但是現在該專案全部移到了www.rforge.net/Rserve,使用REngine作客戶端(和JRI一致),在該網站下可以下載到REngine.jar和RserveEngine.jar兩個檔案。如果用eclipse開發的話,在工程屬性中匯入這兩個外部的jar包,就可以正常使用了。
首先建立一個新的連線,然後就可以使用eval之類的方法將R中的表示式傳到伺服器端,通過R求值後傳回JAVA中REXP型別的變數,然後打印出來,整個過程非常簡單。由於不需要對R進行初始化,因此速度會比較快。在其他系統下可以同時建立多個連線,但是在Windows下只允許同時開啟一個連線,後續的連線都會共有相同的名稱空間。官網上不建議在Windows下使用Rserve,因為會喪失很多效能,他們推薦可以考慮DCOM的方式。不過DCOM那個工程沒有現成的jar包可用,其實如果是拿R做分析系統中的運算引擎,單連線夠用了。
2.2 操作步驟
(一) 在R裡下載“Rserve”包,並安裝
安裝好後,
執行如下命令啟動“Rserver”
> library(Rserve) > Rserve() Starting Rserve... "D:\PROGRA~1\R\R-30~1.1\library\Rserve\libs\i386\Rserve.exe" > |
(二) 建立java工程,匯入必要的包,寫出測試用例
目錄結構如下(標紅色的是需要的):
Test.java 內容
package com.rTest; import org.rosuda.REngine.REXP; import org.rosuda.REngine.Rserve.RConnection; public class Test { public static void main(String[] args) { try { RConnection c = new RConnection(); REXP x = c.eval("R.version.string"); System.out.println(x.asString()); } catch (Exception e) { e.printStackTrace(); } } } |
執行即可
2.3 可能出現的錯誤
2.3.1 Connection refused: connect
org.rosuda.REngine.Rserve.RserveException: Cannot connect: Connection refused: connect at org.rosuda.REngine.Rserve.RConnection.<init>(RConnection.java:88) at org.rosuda.REngine.Rserve.RConnection.<init>(RConnection.java:60) at org.rosuda.REngine.Rserve.RConnection.<init>(RConnection.java:44) at com.rTest.Test.main(Test.java:9) |
這是由於“Rserve” 伺服器沒有啟動起來的原因,試試在R內執行如下語句
> library(Rserve) > Rserve() |
3 JRI 的方式
3.1 介紹
另一種方式是JRI,全名是Java/R Interface,這是一種完全不同的方式,通過呼叫R的動態連結庫從而利用R中的函式等。目前該專案已經成了rJava的子專案,不再提供單獨的JRI的版本。因此使用時簡單地通過install.packages("rJava")安裝rJava就行,在安裝資料夾中,可以看到一個jri的子資料夾,裡面有自帶的例子可以用來測試。
裝好後要修改系統的環境變數,在PATH中新增%R_HOME%/bin和%R_HOME%/library/rJava/jri,注意R_HOME的路徑要正確,重啟系統使之生效。使用時同樣在eclipse裡匯入外部的jar包(在www.rforge.net/rJava下載JRI.jar、REngine.jar和JRIEngine.jar這三個檔案),在rJava包安裝目錄下的jri/examples裡有現成的例子(rtest.java和rtest2.java),可以測試是否成功。
3.2 重要的一步 Spring MVC的專案中呼叫語言
可以說大多數的開發人員最重要的目的就是把這個rjava運用到專案中去。在這個步驟中,我將這個呼叫的方法寫成了一個工具類,但是我遇見了兩個大的問題,第一個,因為在專案是在tomcat中釋出的,所以tomcat在載入的時候沒有找到R的.dll檔案,這個問題可以通過System.out.println(System.getProperty("java.library.path"));這句話,找到你用的那個tomcat下面載入檔案的目錄,將這個jri.dll放進去,重新執行這個就行了。第二個,是我在寫工具類的時候發生的一個錯誤,我沒有考慮到自己會多次使用到這個工具,從而導致我的電腦啟動了很多個JVM,記憶體溢位,宕機。這個問題,是通過一個單例模式的建立來解決的,我只讓這個Rengine在專案中被例項化一次,這樣子,他就只能被啟動一次,不會導致電腦宕機等等
一定要注意jdk的配置路徑,確保環境變數的正確性。
3.3 可能出現的錯誤
3.3.1 Cannot find JRI native library!
Press <Enter> to continue (time to attach the debugger if necessary) Creating Rengine (with arguments) Cannot find JRI native library! Please make sure that the JRI native library is in a directory listed in java.library.path. java.lang.UnsatisfiedLinkError: no jri in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860) at java.lang.Runtime.loadLibrary0(Runtime.java:845) at java.lang.System.loadLibrary(System.java:1084) at org.rosuda.JRI.Rengine.<clinit>(Rengine.java:19) at com.rTest.rtest2.main(rtest2.java:73) |
檢查下path是否正確,如果正確 ,如果配置環境正確,1)用System.out.println(System.getProperty("java.library.path"));輸出java.library.path,結果如下:
D:\develop\Java\jdk1.7.0_40\bin;D:\develop\Java\apache-tomcat-8.0.0-RC5\bin
這個資訊中的前者是java的安裝目錄,後者是tomcat的安裝目錄,把jri.dll分別拷到這兩個目錄。然後測試問題是否解決。