1. 程式人生 > >JAVA呼叫R語言

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.1.1 install.packages("rJava")安裝rJava(如第一種方式一樣選擇映象安裝) 3.1.2 安裝完成後再安裝目錄可以在R的安裝目錄看到如下的目錄結構: 3.1.3 接下來依據這個目錄結構設定環境變數: R_HOME=C:\Program Files\R\R-3.3.1 PATH後新增C:\Program Files\R\R-3.3.1\bin\x64;C:\Program Files\R\R-3.3.1\library\rJava\jri;(可以用%R_HOME%的寫法),但是要特別注意“bin\x64”,系統是64就指定x64資料夾,32位就指定i386資料夾,否則會找不到依賴庫;同理rJava\jri下用的dll檔案也要與計算機位數一致; 3.1.4 環境變數配置完成後把安裝目錄下jri資料夾下的JRI.jar、REngine.jar和JRIEngine.jar放進Java工程新增到編譯路徑。到這裡Java呼叫R的橋樑就搭建好了;

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分別拷到這兩個目錄。然後測試問題是否解決。