我的小工具,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();
}
}
}