JNI --&-- JNA

    最近寫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);
	}
	
}
相關文章
相關標籤/搜索