最近寫SDK,解釋下什麼是SDK,SDK通常是一些被軟件工程師用於爲特定的軟件包、軟件框架、硬件平臺、操做系統等創建應用軟件的開發工具的集合。開發SDK時使用JNI去調用SO或DLL是一件多麼痛苦的事情啊,痛苦的讓我有點想去學C的衝動。首先來解釋下SO和DLL吧,SO和DLL是使用C語言來寫的一個共享庫。下面說說使用JNI和JNA的具體步驟吧: java
首先是讓人灰常頭痛的JNI: 程序員
一:生成NativeJNIHelloWord.java文件 windows
public class NativeJNIHelloWord{ 框架
public native void displayHello(); jvm
static{ socket
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); } }