使用 rJava 从 R 使用 Jackcess
Use Jackcess from R using rJava
我对 Java
不太熟悉,但我尝试在 R
中完成此任务(我的最爱)!
有一个名为 Jackcess
. I want to connect to this library and open an MS Access 2003 .mdb
file in it. Jackcess cookbook 的 Java
库告诉我使用这个库的第一步是:
Database db = DatabaseBuilder.open(new File("mydb.mdb"));
或者如@Gord 所建议的,
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
但我卡在了这第一步。
我已经安装了 Java 和 rJava 并设置了有关目录的所有内容。
这是我在 R
中的代码
library(rJava)
.jinit()
.jaddClassPath("java/jackcess-2.1.2.jar") # there I have put the downloaded jar file of Jackcess
# .jaddClassPath("java/commons-logging-1.2.jar") # this is the commons-logging class that Jackcess depends on, commented to replicate problem 2] in my question.
file.name <- "D:/63.mdb" # some data base .mdb file (containing only tables)
file <- .jnew("java/io/File",file.name)
dbbo <- .jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
[编辑:我发现我有两个问题,一个解决了,一个还没有。]
到目前为止一切正常,但从现在开始我遇到了一些问题:
1] 正确调用 Jackcess 的方法且签名不匹配,这些都不起作用:
dbbo <- .jcall(dbbo,"L<DatabaseBuilder>","setFile",file)
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder","setFile",file)
我收到这个错误:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/DatabaseBuilder", :
method setFile with signature (Ljava/io/File;)Lcom/healthmarketscience/jackcess/DatabaseBuilder not found
好吧,我找到了这一步的答案,我只需要在 class 定义字符串的末尾添加一个分号 (;
)。
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder;","setFile",file)
2]正确调用open
方法,我的第一轮尝试:
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
我得到这个错误:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
我用谷歌搜索发现 Jackcess 依赖于一些名为 commons-logging 的库,因此下载并将其添加到 classpath 解决了这个问题
3]正确调用open
方法,我的第二轮尝试:with commons-logging in classpath
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
这给了我这个错误:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: Could not initialize class com.healthmarketscience.jackcess.impl.DatabaseImpl
对这个错误有什么想法吗?
[注意]:一些答案是在我编辑之前建议的,所以它们现在看起来无关紧要,但我在上面解释的步骤中使用了它们。
以下代码显示了 Java 中使用 "real" DatabaseBuilder
对象的 .setFile
和 .open
方法的替代方法:
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
在 rJava 中尝试类似的东西,看看它是否适合你。
编辑回复:更新问题
您提到您添加了 Apache commons-logging to your CLASSPATH, but Jackcess also relies on Apache commons-lang v2.x( 而不是 v3.x),因此尝试下载它并将其包含在您的 CLASSPATH 中还有。
3 条建议:
在您的类路径中包含 commons-lang-2.0.jar,类似于
rJava::.jaddClassPath("commons-lang-2.0.jar")
简单的方法是像这样尝试使用 J() 调用:
dbb <- rJava::.jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
dbjfile <- rJava::.jnew('java/io/File', "D:/63.mdb")
dbop <- rJava::J(dbb, "open", dbjfile)
尽管如此,如果您真的想以低级方式进行操作,可以尝试以下方法:
dbop <- .jcall(
"RJavaTools"
, "Ljava/lang/Object;"
, "invokeMethod"
, .jcall(dbb, "Ljava/lang/Class;", "getClass")
, .jcast(dbb, "java/lang/Object")
, .jnew("java/lang/String", "open")
, .jarray(list(dbjfile), "java/lang/Object", dispatch = FALSE)
, .jarray(rJava:::._java_class_list(list(dbjfile)), "java/lang/Class", dispatch = FALSE)
, use.true.class = TRUE
, evalString = TRUE
, evalArray = FALSE
)
我对 Java
不太熟悉,但我尝试在 R
中完成此任务(我的最爱)!
有一个名为 Jackcess
. I want to connect to this library and open an MS Access 2003 .mdb
file in it. Jackcess cookbook 的 Java
库告诉我使用这个库的第一步是:
Database db = DatabaseBuilder.open(new File("mydb.mdb"));
或者如@Gord 所建议的,
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
但我卡在了这第一步。
我已经安装了 Java 和 rJava 并设置了有关目录的所有内容。
这是我在 R
library(rJava)
.jinit()
.jaddClassPath("java/jackcess-2.1.2.jar") # there I have put the downloaded jar file of Jackcess
# .jaddClassPath("java/commons-logging-1.2.jar") # this is the commons-logging class that Jackcess depends on, commented to replicate problem 2] in my question.
file.name <- "D:/63.mdb" # some data base .mdb file (containing only tables)
file <- .jnew("java/io/File",file.name)
dbbo <- .jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
[编辑:我发现我有两个问题,一个解决了,一个还没有。] 到目前为止一切正常,但从现在开始我遇到了一些问题:
1] 正确调用 Jackcess 的方法且签名不匹配,这些都不起作用:
dbbo <- .jcall(dbbo,"L<DatabaseBuilder>","setFile",file)
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder","setFile",file)
我收到这个错误:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/DatabaseBuilder", :
method setFile with signature (Ljava/io/File;)Lcom/healthmarketscience/jackcess/DatabaseBuilder not found
好吧,我找到了这一步的答案,我只需要在 class 定义字符串的末尾添加一个分号 (;
)。
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder;","setFile",file)
2]正确调用open
方法,我的第一轮尝试:
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
我得到这个错误:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
我用谷歌搜索发现 Jackcess 依赖于一些名为 commons-logging 的库,因此下载并将其添加到 classpath 解决了这个问题
3]正确调用open
方法,我的第二轮尝试:with commons-logging in classpath
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
这给了我这个错误:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: Could not initialize class com.healthmarketscience.jackcess.impl.DatabaseImpl
对这个错误有什么想法吗?
[注意]:一些答案是在我编辑之前建议的,所以它们现在看起来无关紧要,但我在上面解释的步骤中使用了它们。
以下代码显示了 Java 中使用 "real" DatabaseBuilder
对象的 .setFile
和 .open
方法的替代方法:
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
在 rJava 中尝试类似的东西,看看它是否适合你。
编辑回复:更新问题
您提到您添加了 Apache commons-logging to your CLASSPATH, but Jackcess also relies on Apache commons-lang v2.x( 而不是 v3.x),因此尝试下载它并将其包含在您的 CLASSPATH 中还有。
3 条建议:
在您的类路径中包含 commons-lang-2.0.jar,类似于
rJava::.jaddClassPath("commons-lang-2.0.jar")
简单的方法是像这样尝试使用 J() 调用:
dbb <- rJava::.jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
dbjfile <- rJava::.jnew('java/io/File', "D:/63.mdb")
dbop <- rJava::J(dbb, "open", dbjfile)
尽管如此,如果您真的想以低级方式进行操作,可以尝试以下方法:
dbop <- .jcall(
"RJavaTools"
, "Ljava/lang/Object;"
, "invokeMethod"
, .jcall(dbb, "Ljava/lang/Class;", "getClass")
, .jcast(dbb, "java/lang/Object")
, .jnew("java/lang/String", "open")
, .jarray(list(dbjfile), "java/lang/Object", dispatch = FALSE)
, .jarray(rJava:::._java_class_list(list(dbjfile)), "java/lang/Class", dispatch = FALSE)
, use.true.class = TRUE
, evalString = TRUE
, evalArray = FALSE
)