1. 程式人生 > >我的小工具,java版串列埠讀寫卡測試工具

我的小工具,java版串列埠讀寫卡測試工具

工作過程中,經常需要和卡片打交道,如何快速的讀寫卡,提高些工作效率呢?業餘時間,搞了個讀寫卡測試工具,

通過串列埠操作讀卡器。我把車載機改造為串列埠的讀卡器,配合這個工具就可以使用了。如果有網友想使用這個工具,得自己

做個下位機讀卡器了。指令是透傳的,監控發出來的指令就可以做個下位機。可在我的資源中下載使用(通過工具打包成exe了,若執行不起來注意java的環境配置)。我的qq534117529

先附個截圖:


準備工作:

首先到SUN官網下載一個zip包:javacomm20-win32.zip

其中重要的有這幾個檔案:

win32com.dll

comm.jar

javax.comm.properties


按照說明配置好環境,如下:

將win32com.dll複製到<JDK>\bin目錄下;將comm.jar複製到<JDK>\lib;把 javax.comm.properties也同樣拷貝到<JDK>\lib目錄下。然而在真正執行使用串列埠包的時候,僅作這些是不夠的。因 為通常當執行“java MyApp”的時候,是由JRE下的虛擬機器啟動MyApp的。而我們只複製上述檔案到JDK相應目錄下,所以應用程式將會提示找不到串列埠。解決這個問題的 方法很簡單,我們只須將上面提到的檔案放到JRE相應的目錄下就可以了

到這一個可以java 串列埠開發環境就搭建完成了。

串列埠讀寫程式碼
CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(com);//1,先拿到Identifier
//其中com是String型別的,傳入的是串列埠名com="COM1";
SerialPort port = (SerialPort)portID.open("MyComm", 100000000);//2,開啟串列埠
//"MyComm"是串列埠名,100000000是串列埠過期時間(ms)。
port.setSerialPortParams(rate, databits,stopbit, parity);//3,設定串列埠屬性
//rate 波特率(預設9600),databits載波位(預設8),stopbit停止位(預設1),parity校驗位(預設0無校驗)
port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);//4(可選)設定資料流控制模式,預設為無
port.close();//關閉串列埠
3、串列埠讀入寫出流。
OutputStream os=port.getOutputStream();//拿到寫出流。寫出流就隨便寫就行。
port.getOutputStream().flush();//寫完要記得做一次衝一下緩衝區
InputStream is= port.getInputStream();//拿到讀入流。
is.read();//每次讀入一個int,這個是個阻塞函式,在無資料的時候會中斷。
4、串列埠讀入輪詢模式
一種讀取的方式是每次做
         byte b[]=new byte[1024];
         is.read(b);
如果返回的是-1表示無資料。可以中斷幾毫秒然後再去讀。
比較低效的一種讀取模式,但是在使用阻塞函式的時候還是很好用的。
5、串列埠的監聽模式
//5.1首先建立監聽類
public class CommListener implements SerialPortEventListener
//繼承自javax.comm.SerialPortEventListener;
//實現監聽方法public void serialEvent(SerialPortEvent arg0){}
當有新資料進入的時候會被呼叫,傳入javax.comm.SerialPortEvent物件引數。
if (arg0.getEventType()==SerialPortEvent.DATA_AVAILABLE)//如果是有效資料的話就做read
{
        //read();
}
//5.2建立好監聽類以後要在port上新增。
port.addEventListener(commListener);
//其中port是上文開啟的串列埠埠,commListener是上文的監聽器例項
port.notifyOnDataAvailable(true);//設定監聽模式為當有資料到達時喚醒監聽執行緒。

要想更好的使用串列埠,最好再對comm.jar的串列埠包在封裝出來一個串列埠類。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import java.util.ArrayList;
import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;
/**
 * @專案名稱 :illegalsms
 * @檔名稱 :SerialPort.java
 * @所在包 :org.serial
 * @功能描述 :
 * @建立者 :
 * @建立日期 :
 * @修改記錄 :
 */
public class DSerialPort implements Runnable, SerialPortEventListener {

	private String appName = "串列埠通訊測試";
	private int timeout = 0;//open 埠時的等待時間
	private int threadTime = 0;
	public ArrayList listPort;
        public String revStr="";
        public String revStr1="";
	private CommPortIdentifier commPort;
	private SerialPort serialPort;
	private InputStream inputStream;
	private OutputStream outputStream;
        
	public DSerialPort()
        {
            listPort=new ArrayList();    
        }
	/**
	 * @方法名稱 :listPort
	 * @功能描述 :列出所有可用的串列埠
	 * @返回值型別 :void
	 */
	@SuppressWarnings("rawtypes")
	public void listPort(){
		CommPortIdentifier cpid;
		Enumeration en = CommPortIdentifier.getPortIdentifiers();
		
		log("now to list all Port of this PC:" +en);
		
		while(en.hasMoreElements()){
			cpid = (CommPortIdentifier)en.nextElement();
			if(cpid.getPortType() == CommPortIdentifier.PORT_SERIAL){
				log(cpid.getName() + ", " + cpid.getCurrentOwner());
                                listPort.add(cpid.getName());
			}
		}
	}
	
	
	/**
	 * @方法名稱 :selectPort
	 * @功能描述 :選擇一個埠,比如:COM1
	 * @返回值型別 :void
	 *	@param portName
	 */
	@SuppressWarnings("rawtypes")
	public boolean selectPort(String portName){
		
		this.commPort = null;
		CommPortIdentifier cpid;
		Enumeration en = CommPortIdentifier.getPortIdentifiers();
		
		while(en.hasMoreElements()){
			cpid = (CommPortIdentifier)en.nextElement();
			if(cpid.getPortType() == CommPortIdentifier.PORT_SERIAL
					&& cpid.getName().equals(portName)){
				this.commPort = cpid;
				break;
			}
		}
		
	   return openPort();
	}
	
	/**
	 * @方法名稱 :openPort
	 * @功能描述 :開啟SerialPort
	 * @返回值型別 :void
	 */
	private boolean openPort(){
		if(commPort == null)
                {
		    log(String.format("無法找到名字為'%1$s'的串列埠!", commPort.getName()));
                    return false;
                }
		else{
			log("埠選擇成功,當前埠:"+commPort.getName()+",現在例項化 SerialPort:");
			
			try{
				serialPort = (SerialPort)commPort.open(appName, timeout);
				log("例項 SerialPort 成功!");
                
                               // return true;
                   
			}catch(PortInUseException e){
				log(String.format("埠'%1$s'正在使用中!", 
						commPort.getName()));
                                return false;
			}
                         try
                        {
                            serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8,
                                                     SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                        } 
                        catch(UnsupportedCommOperationException e)
                        {
                            log(String.format("埠'%1$s'引數不合法!", 
						commPort.getName()));
                            return false;
                        }
                        return true;        
            
		}
	}
	
	/**
	 * @方法名稱 :checkPort
	 * @功能描述 :檢查埠是否正確連線
	 * @返回值型別 :void
	 */
	private void checkPort(){
		if(commPort == null)
			throw new RuntimeException("沒有選擇埠,請使用 " +
					"selectPort(String portName) 方法選擇埠");
		
		if(serialPort == null){
			throw new RuntimeException("SerialPort 物件無效!");
		}
	}
	
	/**
	 * @方法名稱 :write
	 * @功能描述 :向埠傳送資料,請在呼叫此方法前 先選擇埠,並確定SerialPort正常開啟!
	 * @返回值型別 :void
	 *	@param message
	 */
	public void write(String message) {
		checkPort();
		
		try{
			outputStream = new BufferedOutputStream(serialPort.getOutputStream());
		}catch(IOException e){
			throw new RuntimeException("獲取埠的OutputStream出錯:"+e.getMessage());
		}
		
		try{
			outputStream.write(message.getBytes());
			log("資訊傳送成功!");
		}catch(IOException e){
			throw new RuntimeException("向埠傳送資訊時出錯:"+e.getMessage());
		}finally{
			try{
				outputStream.close();
			}catch(Exception e){
			}
		}
	}
	
	/**
	 * @方法名稱 :startRead
	 * @功能描述 :開始監聽從埠中接收的資料
	 * @返回值型別 :void
	 *	@param time  監聽程式的存活時間,單位為秒,0 則是一直監聽
	 */
	public void startRead(int time){
		checkPort();
		
		try{
			inputStream = new BufferedInputStream(serialPort.getInputStream());
		}catch(IOException e){
			throw new RuntimeException("獲取埠的InputStream出錯:"+e.getMessage());
		}
		
		try{
			serialPort.addEventListener(this);
		}catch(TooManyListenersException e){
			throw new RuntimeException(e.getMessage());
		}
		
		serialPort.notifyOnDataAvailable(true);
		
		log(String.format("開始監聽來自'%1$s'的資料--------------", commPort.getName()));
		if(time > 0){
			this.threadTime = time*1000;
			Thread t = new Thread(this);
			t.start();
			log(String.format("監聽程式將在%1$d秒後關閉。。。。", threadTime));
		}
	}
	
	
	/**
	 * @方法名稱 :close
	 * @功能描述 :關閉 SerialPort
	 * @返回值型別 :void
	 */
	public void close(){
            if(serialPort!=null)
            {
		serialPort.close();
		serialPort = null;
		commPort = null;
            }
	}
	
	
	/**
     *
     * @param msg
     */
    public void log(String msg){
		System.out.println(appName+" --> "+msg);
	}
     public void log2(String msg){
		System.out.println(appName+" --> "+msg);
	}


	/**
	 * 資料接收的監聽處理函式
	 */
	@Override
	public void serialEvent(SerialPortEvent arg0) {
		switch(arg0.getEventType()){
		case SerialPortEvent.BI:/*Break interrupt,通訊中斷*/ 
        case SerialPortEvent.OE:/*Overrun error,溢位錯誤*/ 
        case SerialPortEvent.FE:/*Framing error,傳幀錯誤*/
        case SerialPortEvent.PE:/*Parity error,校驗錯誤*/
        case SerialPortEvent.CD:/*Carrier detect,載波檢測*/
        case SerialPortEvent.CTS:/*Clear to send,清除傳送*/ 
        case SerialPortEvent.DSR:/*Data set ready,資料裝置就緒*/ 
        case SerialPortEvent.RI:/*Ring indicator,響鈴指示*/
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,輸出緩衝區清空*/ 
            break;
        case SerialPortEvent.DATA_AVAILABLE:/*Data available at the serial port,埠有可用資料。讀到緩衝陣列,輸出到終端*/
        	byte[] readBuffer = new byte[1024];
            String readStr="";
            String s2 = "";
            revStr="";
            try {
                
            	while (inputStream.available() > 0) {
                    inputStream.read(readBuffer);
                    readStr += new String(readBuffer).trim();
                }
                
            	s2 = new String(readBuffer).trim();
            	revStr=s2;
                revStr1="接收到埠返回資料(長度為"+readStr.length()+"):"+readStr;
                //log2("接收到埠返回資料(長度為"+readStr.length()+"):"+readStr);
                log2(s2);
            } catch (IOException e) {
            }
		}
	}


	@Override
	public void run() {
		try{
			Thread.sleep(threadTime);
			serialPort.close();
			log(String.format("埠''監聽關閉了!", commPort.getName()));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}