配置並測試rJava(踩坑記錄)

安裝

> install.packages("rJava")
> library(rJava)
> .jinit()
> s <- .jnew("java/lang/String", "Hello World!")
> s
[1] "Java-Object{Hello World!}"

最後出現"Java-Object{Hello World!}"代表R調用JAVA成功。但會有很多問題,如果JDK 的版本不一致會出現以下問題。

1.版本問題

問題復現:

%1 不是有效的 Win32 應用程序。

版本問題,首先確認JDK的版本,其次確認RGUI 的版本,一致即可解決。
解決:
首先確認JDK的版本,如果是第一種就是64位,如果第二種就是32位。
64位的JDK
在這裏插入圖片描述
32位的JDK
在這裏插入圖片描述

確認完後確認RGUI的版本,使二者一致。
在安裝時可以同時安裝 32 / 64 位兩個版本。確認使用的是哪一個

在這裏插入圖片描述

Rstudio通過確認版本

在這裏插入圖片描述

測試

去R的目錄下找JAR包和附贈的測試類,以下是我的安裝目錄,可以參考。也可以去網上檢索。

D:\R\R-3.6.1\library\rJava\jri

測試代碼

import java.io.*;
import java.awt.Frame;
import java.awt.FileDialog;

import java.util.Enumeration;

import org.rosuda.JRI.Rengine;
import org.rosuda.JRI.REXP;
import org.rosuda.JRI.RList;
import org.rosuda.JRI.RVector;
import org.rosuda.JRI.RMainLoopCallbacks;

class TextConsole implements RMainLoopCallbacks
{
    public void rWriteConsole(Rengine re, String text, int oType) {
        System.out.print(text);
    }
    
    public void rBusy(Rengine re, int which) {
        System.out.println("rBusy("+which+")");
    }
    
    public String rReadConsole(Rengine re, String prompt, int addToHistory) {
        System.out.print(prompt);
        try {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            String s=br.readLine();
            return (s==null||s.length()==0)?s:s+"\n";
        } catch (Exception e) {
            System.out.println("jriReadConsole exception: "+e.getMessage());
        }
        return null;
    }
    
    public void rShowMessage(Rengine re, String message) {
        System.out.println("rShowMessage \""+message+"\"");
    }
	
    public String rChooseFile(Rengine re, int newFile) {
	FileDialog fd = new FileDialog(new Frame(), (newFile==0)?"Select a file":"Select a new file", (newFile==0)?FileDialog.LOAD:FileDialog.SAVE);
	fd.show();
	String res=null;
	if (fd.getDirectory()!=null) res=fd.getDirectory();
	if (fd.getFile()!=null) res=(res==null)?fd.getFile():(res+fd.getFile());
	return res;
    }
    
    public void   rFlushConsole (Rengine re) {
    }
	
    public void   rLoadHistory  (Rengine re, String filename) {
    }			
    
    public void   rSaveHistory  (Rengine re, String filename) {
    }			
}

public class rtest {
    public static void main(String[] args) {
	// just making sure we have the right version of everything
	if (!Rengine.versionCheck()) {
	    System.err.println("** Version mismatch - Java files don't match library version.");
	    System.exit(1);
	}
        System.out.println("Creating Rengine (with arguments)");
		// 1) we pass the arguments from the command line
		// 2) we won't use the main loop at first, we'll start it later
		//    (that's the "false" as second argument)
		// 3) the callbacks are implemented by the TextConsole class above
		Rengine re=new Rengine(args, false, new TextConsole());
        System.out.println("Rengine created, waiting for R");
		// the engine creates R is a new thread, so we should wait until it's ready
        if (!re.waitForR()) {
            System.out.println("Cannot load R");
            return;
        }

		/* High-level API - do not use RNI methods unless there is no other way
			to accomplish what you want */
		try {
			REXP x;
			re.eval("data(iris)",false);
			System.out.println(x=re.eval("iris"));
			// generic vectors are RVector to accomodate names
			RVector v = x.asVector();
			if (v.getNames()!=null) {
				System.out.println("has names:");
				for (Enumeration e = v.getNames().elements() ; e.hasMoreElements() ;) {
					System.out.println(e.nextElement());
				}
			}
			// for compatibility with Rserve we allow casting of vectors to lists
			RList vl = x.asList();
			String[] k = vl.keys();
			if (k!=null) {
				System.out.println("and once again from the list:");
				int i=0; while (i<k.length) System.out.println(k[i++]);
			}			

			// get boolean array
			System.out.println(x=re.eval("iris[[1]]>mean(iris[[1]])"));
			// R knows about TRUE/FALSE/NA, so we cannot use boolean[] this way
			// instead, we use int[] which is more convenient (and what R uses internally anyway)
			int[] bi = x.asIntArray();
			{
			    int i = 0; while (i<bi.length) { System.out.print(bi[i]==0?"F ":(bi[i]==1?"T ":"NA ")); i++; }
			    System.out.println("");
			}
			
			// push a boolean array
			boolean by[] = { true, false, false };
			re.assign("bool", by);
			System.out.println(x=re.eval("bool"));
			// asBool returns the first element of the array as RBool
			// (mostly useful for boolean arrays of the length 1). is should return true
			System.out.println("isTRUE? "+x.asBool().isTRUE());

			// now for a real dotted-pair list:
			System.out.println(x=re.eval("pairlist(a=1,b='foo',c=1:5)"));
			RList l = x.asList();
			if (l!=null) {
				int i=0;
				String [] a = l.keys();
				System.out.println("Keys:");
				while (i<a.length) System.out.println(a[i++]);
				System.out.println("Contents:");
				i=0;
				while (i<a.length) System.out.println(l.at(i++));
			}
			System.out.println(re.eval("sqrt(36)"));
		} catch (Exception e) {
			System.out.println("EX:"+e);
			e.printStackTrace();
		}
		
		// Part 2 - low-level API - for illustration purposes only!
		//System.exit(0);
		
        // simple assignment like a<-"hello" (env=0 means use R_GlobalEnv)
        long xp1 = re.rniPutString("hello");
        re.rniAssign("a", xp1, 0);

        // Example: how to create a named list or data.frame
        double da[] = {1.2, 2.3, 4.5};
        double db[] = {1.4, 2.6, 4.2};
        long xp3 = re.rniPutDoubleArray(da);
        long xp4 = re.rniPutDoubleArray(db);
        
        // now build a list (generic vector is how that's called in R)
        long la[] = {xp3, xp4};
        long xp5 = re.rniPutVector(la);

        // now let's add names
        String sa[] = {"a","b"};
        long xp2 = re.rniPutStringArray(sa);
        re.rniSetAttr(xp5, "names", xp2);

        // ok, we have a proper list now
        // we could use assign and then eval "b<-data.frame(b)", but for now let's build it by hand:       
        String rn[] = {"1", "2", "3"};
        long xp7 = re.rniPutStringArray(rn);
        re.rniSetAttr(xp5, "row.names", xp7);
        
        long xp6 = re.rniPutString("data.frame");
        re.rniSetAttr(xp5, "class", xp6);
        
        // assign the whole thing to the "b" variable
        re.rniAssign("b", xp5, 0);
        
        {
            System.out.println("Parsing");
            long e=re.rniParse("data(iris)", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
        }
        {
            System.out.println("Parsing");
            long e=re.rniParse("iris", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
        }
        {
            System.out.println("Parsing");
            long e=re.rniParse("names(iris)", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
            String s[]=x.asStringArray();
            if (s!=null) {
                int i=0; while (i<s.length) { System.out.println("["+i+"] \""+s[i]+"\""); i++; }
            }
        }
        {
            System.out.println("Parsing");
            long e=re.rniParse("rnorm(10)", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
            double d[]=x.asDoubleArray();
            if (d!=null) {
                int i=0; while (i<d.length) { System.out.print(((i==0)?"":", ")+d[i]); i++; }
                System.out.println("");
            }
            System.out.println("");
        }
        {
            REXP x=re.eval("1:10");
            System.out.println("REXP result = "+x);
            int d[]=x.asIntArray();
            if (d!=null) {
                int i=0; while (i<d.length) { System.out.print(((i==0)?"":", ")+d[i]); i++; }
                System.out.println("");
            }
        }

        re.eval("print(1:10/3)");
        
	if (true) {
	    // so far we used R as a computational slave without REPL
	    // now we start the loop, so the user can use the console
	    System.out.println("Now the console is yours ... have fun");
	    re.startMainLoop();
	} else {
	    re.end();
	    System.out.println("end");
	}
    }
}

2.JAR包導入問題

問題復現:
代碼導入後會報錯,JAR包未導入。
在這裏插入圖片描述

導入JAR包,在rJava文件下
在這裏插入圖片描述
在這裏插入圖片描述

導入後報錯消失。注意主函數命名。

在這裏插入圖片描述

3.環境配置問題

問題復現

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:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at org.rosuda.JRI.Rengine.(Rengine.java:19)
at rtest.main(rtest.java:61)
在這裏插入圖片描述
這是環境問題

解決:

配置環境變量:
增加一條R_HOME的環境變量。

R_HOME
D:\R\R-3.6.1

在這裏插入圖片描述
配置Path環境變量注意結尾如果是32位就改爲i386,注意用;分隔。

Path
;%R_HOME%\library\rJava\jri;%R_HOME%\library\rJava\jri\x64;%R_HOME%\bin\D:\R\R-3.6.1\bin\x64

然後問題就演變成第三個了。

4.版本問題

問題復現:

java.lang.UnsatisfiedLinkError: D:\R\R-3.6.1\library\rJava\jri\jri.dll: Can’t load IA 32-bit .dll on a AMD 64-bit platform

在這裏插入圖片描述
這個時候我們查看配置的Path會發現明明已經指向的是x64但是還是出現了32位 不兼容的情況。
在這裏插入圖片描述
查看報錯信息提供的路徑會發現默認指向的.dll文件是32位的。
在這裏插入圖片描述
我們可以將這個.dll文件替換成64位的,如果全部應用的32位則不會出現這個問題。
在這裏插入圖片描述

運行成功!!!

以下是JDK的配置過程,如果想修改JDK版本的話可以參考。

JDK配置

JAVA_HOME

D:\JDK8 

我的 jdk 位置
在這裏插入圖片描述

Path

%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

這個直接複製即可,配上一個bin和jre的bin,前面的JAVA_HOME就是第一步配置好的路徑,算是引用。(注意原來Path的變量值末尾有沒有;號,如果沒有,先輸入;號再輸入上面的代碼)
在這裏插入圖片描述

ClassPath

.;%Java_Home%\bin;%Java_Home%\lib\dt.jar;%Java_Home%\lib\tools.jar

注意前面的"."
在這裏插入圖片描述

總結

錯誤1:%1 不是有效的 Win32 應用程序。
原因:導入rJava過程中, 32位java和64位R不匹配。
解決方法:
查看Java版本: windows命令窗口輸入 Java -version
查看R版本:R studio中菜單 tools->Global Option -> General -> R Version
然後安裝相同的版本就可以了

錯誤2: java.lang.UnsatisfiedLinkError: D:\Program Files\R\R-3.1.2\library\rJava\jri\jri.dll: Can’t find dependent libraries
原因:環境變量沒有配置
解決方法: 重新配置path,增加了%R_HOME%\library\rJava\jri;%R_HOME%\library\rJava\jri\i386;%R_HOME%\bin\i386這兩個路徑(32位指向i386; 64位指向x64)。

如果出現以下錯誤
錯誤3: C:\Program Files\R\R-3.4.3\library\rJava\jri\jri.dll: Can’t load IA 32-bit .dll on a AMD 64-bit platform
原因:你安裝的是64位的系統,而配置變量指向的是32位的路徑。
解決方法:配置變量時候需要指向%R_HOME%\library\rJava\jri\i64;%R_HOME%\bin\i64

參考

基本可以參考:
http://blog.csdn.net/adnerly/article/details/50314731
http://blog.csdn.net/huangyezi123/article/details/42654499
http://blog.sina.com.cn/s/blog_53dd83fd0102xh6r.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章