最近写SDK,解释下什么是SDK,SDK一般是一些被软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。开发SDK时使用JNI去调用SO或DLL是一件多么痛苦的事情啊,痛苦的让我有点想去学C的冲动。首先来解释下SO和DLL吧,SO和DLL是使用C语言来写的一个共享库。下面说说使用JNI和JNA的具体步骤吧:
首先是让人灰常头痛的JNI:
一:生成NativeJNIHelloWord.java文件
public class NativeJNIHelloWord{
public native void displayHello();
static{
System.out.println("hello");
}
static{
System.load("xx.so");
/*
加载so或dll,System.load2.System.load 参数为库文件的绝对路径,可以是任意路径。
例如你可以这样载入一个windows平台下JNI库文件:
System.load("C:\\Documents and Settings\\TestJNI.dll");。
3. System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
例如你可以这样载入一个windows平台下JNI库文件
System. loadLibrary ("TestJNI");
这里,TestJNI.dll 必须是在java.library.path这一jvm变量所指向的路径中。
可以通过如下方法来获得该变量的值:
System.getProperty("java.library.path");
默认情况下,在Windows平台下,该值包含如下位置:
1)和jre相关的一些目录
2)程序当前目录
3)Windows目录
4)系统目录(system32)
5)系统环境变量path指定目录
*/
}
}
二:javac命令将.java文件生成.class文件
三:javah命令将.class文件生成.h头文件 该文件供给C进行调用
java程序员到这里就可以了,剩下的是C程序员给你so或dll文件即可。
JNA解决JNI的缺点:
JNA的开发步骤:
第一步:下载JNA的jar包,可以去com.sun的官网上去下jna-3.0.1.jar
第二步:编写JNA的类,其内部定义接口,使接口实现library接口。
接口内部的方法需要和dll或so内定义的相一致,其中需要注意的是C中的char* 对应java中的String
C中的wchar_t* 对应java的WString,JNA提供一个INSTANCE属性,通过该属性进行调用类中的方法。
public class JNAHelloWord{
public instance Ioftp extends Library{
public void display();
public int FtpRev(WString rfile,int id,String ms);
}
public static Ioftp Instance=(Ioftp)Native.loadLibrary("ftpdll",Ioftp.class);//注意只需要SO或dll的文件名,不需要带后缀
}
以下是真实的java代码:
package com.icms.sdk.oftpd;
public interface IOFTPD {
// 打开连接 host:ip地址 port:端口号
public int FTPopen(String host, int port);
// 关闭连接
public int FTPclose();
// 发送数据 lfile:本地文件名 rfile:远程文件名 msSysCode:系统标识
public int FTPsend(String lfile, String rfile, String msSysCode);
// 接受数据 rfile,远程文件名 lfile,本地文件名 msSysCode:系统标识
public int FTPrecv(String rfile, String lfile, String msSysCode);
// 设置参数(超时时间的设置 id可能有十几种类型)
public int FTPsetflag(int id, int flag);
// 删除文件夹 dir:目录 msSysCode:系统标识
public int FTPrmdir(String dir, String msSysCode);
// 查询文件夹下所有文件列表 dir:目录 msSysCode:系统标识
public String FTPlistForJava(String rPath, String msSysCode);
}
package com.icms.sdk.oftpd;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import com.icms.sdk.util.PropertiesUtil;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;
/**
* 文件传输
* <p>
* <br>
* <b>Package_name:</b>boc.oftpd<br>
* <b>Class_name:</b>FileTransfer.java<br>
* <b>Company:</b>Founder<br>
* <b>Date:</b>Nov 7, 2012 - 10:42:32 AM<br>
*
* @author xg
* </p>
*/
public class JNAFileTransfer implements IOFTPD {
private static final boolean isWindows = System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
private static IOftpd INSTANCE = loadDll();
/**
* 工具类判断操作系统,动态载入dll或so文件
*/
public static IOftpd loadDll() {
IOftpd oftpd = null;
String DLL_FUNCNAME = PropertiesUtil.getProperty("DLL_FUNCNAME");
if (DLL_FUNCNAME == null) {
DLL_FUNCNAME = "ftpdll";
}
String DLL_FILENAME = isWindows ? DLL_FUNCNAME + ".dll" : DLL_FUNCNAME
+ ".so";
File dllFile = new File(new File(System.getProperty("user.dir")),
DLL_FILENAME);
if (!dllFile.exists()) {
fileCopy(DLL_FILENAME);
if (isWindows) {
fileCopy("msvcr100.dll");
}
}
System.load(dllFile.getAbsolutePath());
oftpd = (IOftpd) Native.loadLibrary(DLL_FUNCNAME, IOftpd.class);
return oftpd;
}
/**
* 拷贝文件至{user.dir}目录下
*
* @param filePath
*/
private static void fileCopy(String DLL_FILENAME) {
InputStream in = null;
BufferedOutputStream out = null;
File dllFile = new File(new File(System.getProperty("user.dir")),
DLL_FILENAME);
try {
in = JNAFileTransfer.class.getResourceAsStream("/" + DLL_FILENAME);
byte[] buffer = new byte[512];
out = new BufferedOutputStream(new FileOutputStream(dllFile));
while (true) {
int readed = in.read(buffer);
if (readed <= -1)
break;
out.write(buffer, 0, readed);
}
} catch (Exception e) {
} finally {
if (out != null) {
try {
out.close();
} catch (Exception e) {
}
}
if (in != null) {
try {
in.close();
} catch (Exception e) {
}
}
dllFile = null;
}
}
public interface IOftpd extends Library {
// 打开连接 host:ip地址 port:端口号
public int FTPopen(String host, int port);
// 关闭连接
public int FTPclose();
// 发送数据 lfile:本地文件名 rfile:远程文件名 msSysCode:系统标识
public int FTPsend(WString lfile, WString rfile, String msSysCode);
// 接受数据 rfile,远程文件名 lfile,本地文件名 msSysCode:系统标识
public int FTPrecv(WString rfile, WString lfile, String msSysCode);
// 设置参数(超时时间的设置 id可能有十几种类型)
public int FTPsetflag(int id, int flag);
// 删除文件夹 dir:目录 msSysCode:系统标识
public int FTPrmdir(WString dir, String msSysCode);
// 查询文件夹下所有文件列表 dir:目录 msSysCode:系统标识
public WString FTPlistForJava(WString rPath, String msSysCode);
}
private synchronized static boolean write(String path, String content) {
FileWriter fw = null;
try {
fw = new FileWriter(path, true);
fw.write(content + "\r\n");
fw.flush();
} catch (IOException e) {
} finally {
try {
fw.close();
} catch (IOException e) {
}
}
return true;
}
public int FTPclose() {
return INSTANCE.FTPclose();
}
public String FTPlistForJava(String path, String msSysCode) {
String temp="";
WString list=INSTANCE.FTPlistForJava(new WString(path), msSysCode);
if(list!=null){
temp=list.toString();
}
return temp;
}
public int FTPopen(String host, int port) {
return INSTANCE.FTPopen(host, port);
}
public int FTPrecv(String rfile, String lfile, String msSysCode) {
FTPsetflag();
return INSTANCE.FTPrecv(new WString(rfile), new WString(lfile),msSysCode);
}
public int FTPrmdir(String dir, String msSysCode) {
return INSTANCE.FTPrmdir(new WString(dir), msSysCode);
}
public int FTPsend(String lfile, String rfile, String msSysCode) {
FTPsetflag();
return INSTANCE.FTPsend(new WString(lfile), new WString(rfile),msSysCode);
}
public int FTPsetflag(int id, int flag) {
return INSTANCE.FTPsetflag(id, flag);
}
/**
* 设置文件传输的发送和接收超时时间
*/
private void FTPsetflag() {
/** 设置log日志默认不启用 **/
String FTPLogSwitch = PropertiesUtil.getProperty("FTPLogSwitch");
if (!FTPConstant.FTPLogSetFlag.ISFTPDEBUG.equals(FTPLogSwitch)) {
FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.OFF_FLAG);
} else {
FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.ON_FLAG);
}
// 设置文件发送传输超时时间
int ftpSendTimeout = FTPConstant.FTPSendTimeoutSetFlag.DEFAULT_FLAG;
String FTPsendTimeout = PropertiesUtil.getProperty("sendTimeout");
if (!"".equals(FTPsendTimeout) && null != FTPsendTimeout && ftpSendTimeout < Integer.parseInt(FTPsendTimeout)) {
ftpSendTimeout = Integer.parseInt(FTPsendTimeout);
}
FTPsetflag(FTPConstant.FTPSendTimeoutSetFlag.ID, ftpSendTimeout);
int ftpRecvTimeout = FTPConstant.FTPRecvTimeoutSetFlag.DEFAULT_FLAG;
String recvTimeout = PropertiesUtil.getProperty("recvTimeout");
if (!"".equals(recvTimeout) && null != recvTimeout && ftpRecvTimeout < Integer.parseInt(recvTimeout)) {
ftpRecvTimeout = Integer.parseInt(recvTimeout);
}
FTPsetflag(FTPConstant.FTPRecvTimeoutSetFlag.ID, ftpRecvTimeout);
}
public static void main(String[] args) {
// 1. 新建一个1.txt文件
File tempFile = new File(new File(System.getProperty("user.dir")),"1.txt");
String tempFilePath = tempFile.getAbsolutePath();
write(tempFilePath, "11111111111111111111111111111111111111111111111");
// 2. 获得实例
JNAFileTransfer obj = new JNAFileTransfer();
// 3. 打开链接
obj.FTPopen("192.168.1.244", 10000);
// 4.上传1.txt文件
obj.FTPsend(tempFilePath, "1.txt", "01");
// 5. 删除本地文件
tempFile.delete();
// 6. 下载1.txt文件
obj.FTPrecv("1.txt", tempFilePath, "01");
// 6. list
System.out.println(obj.FTPlistForJava("sdk", "01"));
//7. 删除远程文件夹
obj.FTPrmdir("sdk/ftplog", "01");
// 8. 删除临时文件
File temp = new File(tempFilePath);
System.out.println(temp.exists());
temp.delete();
// 7. 关闭链接
obj.FTPclose();
}
}
package com.icms.sdk.oftpd;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import com.icms.sdk.util.PropertiesUtil;
/**
* 文件传输海外版本JNI实现,目前仅支持AIX操作系统
* <p>
* <br>
* <b>Package_name:</b>com.icms.sdk.oftpd<br>
* <b>Class_name:</b>JNIFileTransfer.java<br>
* <b>Company:</b>Founder<br>
* <b>Date:</b>Nov 7, 2012 - 10:42:32 AM<br>
*
* @author xg
* </p>
*/
public class JNIFileTransfer implements IOFTPD {
private static IOftpd INSTANCE = loadDll();
/**
* 工具类判断操作系统,动态载入dll或so文件
*/
public static IOftpd loadDll() {
IOftpd oftpd = null;
String DLL_FUNCNAME = PropertiesUtil.getProperty("DLL_FUNCNAME");
String DLL_FILENAME = DLL_FUNCNAME+ ".so";
File dllFile = new File(new File(System.getProperty("user.dir")),DLL_FILENAME);
if (!dllFile.exists()) {
fileCopy(DLL_FILENAME);
}
System.load(dllFile.getAbsolutePath());
return oftpd;
}
/**
* 拷贝文件至{user.dir}目录下
*
* @param filePath
*/
private static void fileCopy(String DLL_FILENAME) {
InputStream in = null;
BufferedOutputStream out = null;
File dllFile = new File(new File(System.getProperty("user.dir")),
DLL_FILENAME);
try {
in = JNIFileTransfer.class.getResourceAsStream("/" + DLL_FILENAME);
byte[] buffer = new byte[512];
out = new BufferedOutputStream(new FileOutputStream(dllFile));
while (true) {
int readed = in.read(buffer);
if (readed <= -1)
break;
out.write(buffer, 0, readed);
}
} catch (Exception e) {
} finally {
if (out != null) {
try {
out.close();
} catch (Exception e) {
}
}
if (in != null) {
try {
in.close();
} catch (Exception e) {
}
}
dllFile = null;
}
}
public class IOftpd {
//打开连接 host:ip地址 port:端口号
public native int FTPopen(String host, int port);
//关闭连接
public native int FTPclose();
//发送数据 lfile:本地文件名 rfile:远程文件名 msSysCode:系统标识
public native int FTPsend(String lfile, String rfile, String msSysCode);
//接受数据 rfile:远程文件名 lfile:本地文件名 msSysCode:系统标识
public native int FTPrecv(String rfile, String lfile, String msSysCode);
//设置参数(超时时间的设置 id可能有十几种类型)
public native int FTPsetflag(int id, int flag);
//删除文件夹 dir:目录 msSysCode:系统标识
public native int FTPrmdir(String dir, String msSysCode);
//查询文件夹下所有文件列表 dir:目录 msSysCode:系统标识
public native String FTPlist(String dir, String msSysCode);
}
private synchronized static boolean write(String path, String content) {
FileWriter fw = null;
try {
fw = new FileWriter(path, true);
fw.write(content + "\r\n");
fw.flush();
} catch (IOException e) {
} finally {
try {
fw.close();
} catch (IOException e) {
}
}
return true;
}
public int FTPclose() {
return INSTANCE.FTPclose();
}
public String FTPlistForJava(String path, String msSysCode) {
return INSTANCE.FTPlist(path, msSysCode);
}
public int FTPopen(String host, int port) {
return INSTANCE.FTPopen(host, port);
}
public int FTPrecv(String rfile, String lfile, String msSysCode) {
FTPsetflag();
return INSTANCE.FTPrecv(rfile, lfile,msSysCode);
}
public int FTPrmdir(String dir, String msSysCode) {
return INSTANCE.FTPrmdir(dir, msSysCode);
}
public int FTPsend(String lfile, String rfile, String msSysCode) {
FTPsetflag();
return INSTANCE.FTPsend(lfile, rfile,msSysCode);
}
public int FTPsetflag(int id, int flag) {
return INSTANCE.FTPsetflag(id, flag);
}
/**
* 设置文件传输的发送和接收超时时间
*/
private void FTPsetflag() {
/** 设置log日志默认不启用 **/
String FTPLogSwitch = PropertiesUtil.getProperty("FTPLogSwitch");
if (!FTPConstant.FTPLogSetFlag.ISFTPDEBUG.equals(FTPLogSwitch)) {
FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.OFF_FLAG);
} else {
FTPsetflag(FTPConstant.FTPLogSetFlag.ID, FTPConstant.FTPLogSetFlag.ON_FLAG);
}
// 设置文件发送传输超时时间
int ftpSendTimeout = FTPConstant.FTPSendTimeoutSetFlag.DEFAULT_FLAG;
String FTPsendTimeout = PropertiesUtil.getProperty("sendTimeout");
if (!"".equals(FTPsendTimeout) && null != FTPsendTimeout && ftpSendTimeout < Integer.parseInt(FTPsendTimeout)) {
ftpSendTimeout = Integer.parseInt(FTPsendTimeout);
}
FTPsetflag(FTPConstant.FTPSendTimeoutSetFlag.ID, ftpSendTimeout);
int ftpRecvTimeout = FTPConstant.FTPRecvTimeoutSetFlag.DEFAULT_FLAG;
String recvTimeout = PropertiesUtil.getProperty("recvTimeout");
if (!"".equals(recvTimeout) && null != recvTimeout && ftpRecvTimeout < Integer.parseInt(recvTimeout)) {
ftpRecvTimeout = Integer.parseInt(recvTimeout);
}
FTPsetflag(FTPConstant.FTPRecvTimeoutSetFlag.ID, ftpRecvTimeout);
}
public static void main(String[] args) {
// 1. 新建一个1.txt文件
File tempFile = new File(new File(System.getProperty("user.dir")),"1.txt");
String tempFilePath = tempFile.getAbsolutePath();
write(tempFilePath, "11111111111111111111111111111111111111111111111");
// 2. 获得实例
JNIFileTransfer obj = new JNIFileTransfer();
// 3. 打开链接
obj.FTPopen("192.168.1.244", 10000);
// 4.上传1.txt文件
obj.FTPsend(tempFilePath, "1.txt", "01");
// 5. 删除本地文件
tempFile.delete();
// 6. 下载1.txt文件
obj.FTPrecv("1.txt", tempFilePath, "01");
// 6. list
System.out.println(obj.FTPlistForJava("sdk", "01"));
obj.FTPrmdir("sdk/ftplog", "01");
// 8. 删除临时文件
File temp = new File(tempFilePath);
System.out.println(temp.exists());
temp.delete();
// 7. 关闭链接
obj.FTPclose();
}
}
package com.icms.sdk.oftpd;
import java.io.File;
import com.icms.sdk.util.FTPUtil;
import com.icms.sdk.util.PropertiesUtil;
import com.icms.sdk.util.UserDFException;
/**
* 文件传输对外仅暴露这个工具类型
* @author Administrator
*
*/
public class OftpdUtil {
/**
* 获取socket操作时间
* getSocketOpTime
* @return
* @author huangyi
*/
public static int getSocketOpTime(){
int otTimeout = FTPUtil.DEFAULT_OT_TIMEOUT;
String socketTimeout = PropertiesUtil.getProperty("OT_TIMEOUT");
if (!"".equals(socketTimeout) && null != socketTimeout) {
otTimeout = Integer.parseInt(socketTimeout);
}
return otTimeout;
}
public void uploadFile(String ip, int port, String localFile, String ftpFile, String systemId) throws UserDFException {
FileTransfer tran=new FileTransfer();
// 打开端口
int rtnflag = tran.FTPopen(ip, port);
if(rtnflag!=0){
throw new UserDFException("FTPopen Exception, rtnflag="+rtnflag);
}
// 上传文件 localPath ftpPath
if(tran.FTPsend(localFile, ftpFile, systemId)!=0){
throw new UserDFException("FTPsend Exception, rtnflag="+rtnflag);
}
// 关闭端口
if(rtnflag==0){
tran.FTPclose();
}
}
/**
*多文件上传
* @param ip
* @param port
* @param localPath
* @param ftpPath
* @param systemId
* @throws UserDFException
*/
public void uploadFiles(String ip, int port, String localPath, String ftpPath, String systemId) throws UserDFException {
// 打开端口
FileTransfer tran=new FileTransfer();
int rtnflag = tran.FTPopen(ip, port);
if(rtnflag!=0){
throw new UserDFException("FTPopen Exception, rtnflag="+rtnflag);
}
File file = new File(localPath);
if (!file.exists()) {
throw new UserDFException("localPath not exists, FilePath="+localPath);
}
// 上传文件 localPath ftpPath
String[] sb = file.list();
for(int i=0;i<sb.length;i++){
if(tran.FTPsend(localPath+"/"+sb[i], ftpPath+"/"+sb[i], systemId)!=0){
throw new UserDFException("FTPsend Exception, rtnflag="+rtnflag);
}
}
// 关闭端口
if(rtnflag==0){
tran.FTPclose();
}
}
/**
* 多文件下载
* downloadFile
* @param ftpPath
* @param localPath
* @param systemId
* @author huangyi
* @throws UserDFException
*/
public void downloadFile(String ip, int port, String ftpPath, String localPath, String systemId) throws UserDFException {
FileTransfer tran=new FileTransfer();
boolean flag = true;
int rtnflag = -1;
// 打开端口
rtnflag = tran.FTPopen(ip, port);
if(rtnflag!=0){
throw new UserDFException("FTPopen Exception, rtnflag="+rtnflag);
}
// 循环下载文件
String File = tran.FTPlistForJava(ftpPath, systemId);
String[] fileList = File.split("\\|");
for(int i=0;i<fileList.length;i++){
if(tran.FTPrecv(ftpPath+"/"+fileList[i], localPath+"/"+fileList[i], systemId)!=0){
flag=false;
throw new UserDFException("FTPrecv Exception, rtnflag="+rtnflag);
}
}
// 删除ftp目录文件
if(flag){
tran.FTPrmdir(ftpPath, systemId);
}
// 关闭端口
if(rtnflag==0){
tran.FTPclose();
}
}
}
package com.icms.sdk.oftpd;
public class FileTransfer implements IOFTPD {
private IOFTPD oftpd=getInstance();
private static final boolean isAIX = System.getProperty("os.name").toLowerCase().indexOf("aix") != -1;
private IOFTPD getInstance() {
IOFTPD oftpd=null;
if(isAIX){
oftpd=new JNIFileTransfer();
}else{
oftpd=new JNAFileTransfer();
}
return oftpd;
}
public int FTPclose() {
return 0;
}
public String FTPlistForJava(String path, String msSysCode) {
return oftpd.FTPlistForJava(path, msSysCode);
}
public int FTPopen(String host, int port) {
return oftpd.FTPopen(host, port);
}
public int FTPrecv(String rfile, String lfile, String msSysCode) {
return oftpd.FTPrecv(rfile, lfile, msSysCode);
}
public int FTPrmdir(String dir, String msSysCode) {
return oftpd.FTPrmdir(dir, msSysCode);
}
public int FTPsend(String lfile, String rfile, String msSysCode) {
return oftpd.FTPsend(lfile, rfile, msSysCode);
}
public int FTPsetflag(int id, int flag) {
return oftpd.FTPsetflag(id, flag);
}
}
来源:oschina
链接:https://my.oschina.net/u/656749/blog/96703