SerailValidator.validBytes() 是个校验方法
CardManager.isCardValid() 是查询卡的有效性
CardManager.saveCardRecord() 是执行INSERT
package com.ditian.serial;import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import java.io.*;
import java.util.*;
import javax.comm.*;public class SerialTerminal implements SerialPortEventListener, Runnable {
private InputStream in = null;
private OutputStream out = null;
private SerialPort serialPort = null;public static final String ValidStr = "S98";
public static final String InvalidStr = "S97";public static void main(String[] args) throws IOException {
SerialTerminal term = new SerialTerminal(args.length > 0 ? args[0]
: null);
}
public SerialTerminal(String port) {
System.out.println("serail termina init...............");
if (port == null) {
port = "COM2";
}
CommPortIdentifier portId = null;
System.out.println("Searching for port: " + port);
Enumeration portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
CommPortIdentifier cpi = (CommPortIdentifier) portList
.nextElement();
if (cpi.getPortType() == CommPortIdentifier.PORT_SERIAL) {
if (cpi.getName().equals(port)) {
System.out.println("Found port: " + cpi.getName());
portId = cpi;
break;
}
}
}
if (portId == null) {
System.out.println("port " + port + " not found.");
}
try {
serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//serialPort.enableReceiveTimeout(2000);serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnCTS(true);
serialPort.notifyOnDSR(true);
serialPort.notifyOnRingIndicator(true);
serialPort.notifyOnCarrierDetect(true);
serialPort.notifyOnOverrunError(true);
serialPort.notifyOnParityError(true);
serialPort.notifyOnFramingError(true);
serialPort.notifyOnBreakInterrupt(true);
//serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnOutputEmpty(true);in = serialPort.getInputStream();
out = serialPort.getOutputStream();OutputStream out = serialPort.getOutputStream();
} catch (PortInUseException e) {
System.out.println("Port " + port + " is in use.");
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
public void close() {
try {
in.close();
out.close();
serialPort.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//implement Runnable
public void run() {
try
{
synchronized (this) {
wait(10000);
}
}
catch (InterruptedException e)
{
}if (this.DA) {
readData(); 
notifyAll();
}
}public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.DATA_AVAILABLE:
this.DA = true;
readData();
try {
wait(5000);
} catch (Exception e){

notifyAll();
break;
}
}private boolean DA;synchronized private void readData() {
if (!DA) return;byte[] buf = new byte[12];
int r = 0;
try {
while ((r = in.read(buf)) != -1) {
System.out.println("IN: " + new String(buf, 0, r));
//validation received data
boolean bb = false;bb = SerailValidator.validBytes(buf);
String cardNo = "";
if (bb) {
cardNo = new String(buf, 0, r - 1);
// validation card
bb = CardManager.isCardValid(cardNo); 
}
//try {Thread.sleep(50);} catch (Exception e) {}
if (bb) { 
System.out.println("valid");
for (int k = 0; k < ValidStr.length(); k++) {
out.write(ValidStr.charAt(k)); 

try {Thread.sleep(100);} catch (Exception e) {}
} else {
System.out.println("invalid");
for (int k = 0; k < InvalidStr.length(); k++) {
out.write(InvalidStr.charAt(k));
}

//save card record 
if (bb) CardManager.saveCardRecord(cardNo); }
} catch (IOException e) {
System.err.println("ERR: " + e.getMessage());
}
this.DA = false;
notifyAll();
}
}

解决方案 »

  1.   

    后来我同步了一下,但还是不行,仍会有个别时间有错误发生
    public void run() {
    try {
    synchronized (this) {
    wait(10000);
    }
    } catch (InterruptedException e) {
    }
    if (this.DA) {
    //readData();
    }
    } public void serialEvent(SerialPortEvent event) {
    switch (event.getEventType()) {
    case SerialPortEvent.BI:
    case SerialPortEvent.OE:
    case SerialPortEvent.FE:
    case SerialPortEvent.PE:
    case SerialPortEvent.CD:
    case SerialPortEvent.CTS:
    case SerialPortEvent.DSR:
    case SerialPortEvent.RI:
    case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
    break;
    case SerialPortEvent.DATA_AVAILABLE:
    while (this.DA) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
    }
    //synchronized (lock) {
    this.DA = true;
    readData();
    //}
    break;
    }
    } private boolean DA; synchronized private void readData() {
    while (!this.DA) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
    }

    //synchronized (lock) {
    byte[] buf = new byte[12];
    int r = 0;
    try {
    while ((r = in.read(buf)) != -1) {
    System.out.println("IN: " + new String(buf, 0, r));
    //validation received data
    boolean bb = false; bb = SerailValidator.validBytes(buf);
    String cardNo = "";
    if (bb) {
    cardNo = new String(buf, 0, r - 1);
    // validation card
    bb = CardManager.isCardValid(cardNo);
    }

    if (bb) {
    System.out.println("valid");
    for (int k = 0; k < ValidStr.length(); k++) {
    out.write(ValidStr.charAt(k));
    }
    } else {
    System.out.println("invalid");
    for (int k = 0; k < InvalidStr.length(); k++) {
    out.write(InvalidStr.charAt(k));
    }
    }
    //save card record
    if (bb)
    CardManager.saveCardRecord(cardNo);
    }
    } catch (IOException e) {
    System.err.println("ERR: " + e.getMessage());
    }
    this.DA = false;
    notifyAll();
    //}
    }
      

  2.   

    不好意思,刚才直接从eclipse把代码拷出来,太乱了。我整理一下。
    public void run() {
        try {
            synchronized (this) {
                wait(10000);
            }
        } catch (InterruptedException e) {
        }
        if (this.DA) {
            //readData();        
        }        
    }
     
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
        case SerialPortEvent.BI:
        case SerialPortEvent.OE:
        case SerialPortEvent.FE:
        case SerialPortEvent.PE:
        case SerialPortEvent.CD:
        case SerialPortEvent.CTS:
        case SerialPortEvent.DSR:
        case SerialPortEvent.RI:
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
            break;
        case SerialPortEvent.DATA_AVAILABLE:
            while (this.DA) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            //synchronized (lock) {
                this.DA = true;
                readData();
            //}
            break;
        }
    }
     
    private boolean DA;
     
    synchronized private void readData() {
        while (!this.DA) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        
        //synchronized (lock) {
            byte[] buf = new byte[12];
            int r = 0;
            try {
                while ((r = in.read(buf)) != -1) {
                    System.out.println("IN: " + new String(buf, 0, r));
                    //validation received data
                    boolean bb = false;
     
                    bb = SerailValidator.validBytes(buf);
                    String cardNo = "";
                    if (bb) {
                        cardNo = new String(buf, 0, r - 1);
                        //                    validation card
                        bb = CardManager.isCardValid(cardNo);
                    }
                    
                    if (bb) {
                        System.out.println("valid");
                        for (int k = 0; k < ValidStr.length(); k++) {
                            out.write(ValidStr.charAt(k));
                        }
                    } else {
                        System.out.println("invalid");
                        for (int k = 0; k < InvalidStr.length(); k++) {
                            out.write(InvalidStr.charAt(k));
                        }
                    }
                    //save card record
                    if (bb)
                        CardManager.saveCardRecord(cardNo);
                }
            } catch (IOException e) {
                System.err.println("ERR: " + e.getMessage());
            }
            this.DA = false;
            notifyAll();
        //}
    }
      

  3.   

    问题出在这里,
    while ((r = in.read(buf)) != -1) 
    既然出现了只读了8位就结束了的情况,你就不能够用 r != -1作为条件来判断一次读取的条件,因为在你读到后4位之前, r=-1已经满足,循环就跳出了。所以,你应该判断读过来的是不是12位,如果不是,就暂存前8位的数据,然后再读下一次,补全后4位。收集齐了12位之后,再调用 bb = SerailValidator.validBytes(buf);
      

  4.   

    perryhg(Perry)说的问题原因不对,但是解决方案是应该暂存前8位,线程同步就可以搞好。已解决。谢谢大家。