代码如下:package com.main2;import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;public class Main {

public static void main(String[] args) {
try{
Test test = new Test();
test.start();
}catch(Exception e){
e.printStackTrace();
}
}
}
class Test extends Thread implements SerialPortEventListener {

static Enumeration portList;   
    static CommPortIdentifier portId;
    static SerialPort serialPort;
    static OutputStream outputStream;
    static InputStream inputStream;
    static BufferedReader br;

public Test(){
try{
portId = CommPortIdentifier.getPortIdentifier("COM3");
        //打开通讯   
        serialPort = (SerialPort)portId.open("SimpleWriteApp", 2000);
        serialPort.setRTS(false);
//         serialPort.enableReceiveTimeout(0); //打开串口之后,读取之前
//         serialPort.enableReceiveThreshold(0);
        serialPort.setSerialPortParams(2400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
}catch(Exception e){
e.printStackTrace();
}
} public void run() {
byte[]  bt = new byte[]{(byte)0xaa,(byte)0x00,(byte)0xdb,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x55};

send(serialPort, bt);
}

private void send(SerialPort sPort, byte[] bt) {
try {
//发送命令
outputStream = sPort.getOutputStream();
            outputStream.write(bt);
            outputStream.flush();
            outputStream.close();
            System.out.println("command   has   been   send");
            
            Thread.sleep(100);

            //接收返回值
sPort.setRTS(true);
inputStream = sPort.getInputStream();
br = new BufferedReader(new InputStreamReader(inputStream));

//注册事件监听
sPort.addEventListener(this);
sPort.notifyOnDataAvailable(true);
} catch (IOException e) {
e.printStackTrace();
}catch (TooManyListenersException e) {
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
}

public synchronized void serialEvent(SerialPortEvent ev) {
try{
if (ev.getEventType() == ev.DATA_AVAILABLE){

//方法一 【抛出异常java.io.IOException : underlying input stream returned zero bytes】
String line = null;
while ((line=br.readLine()) != null) {
System.out.println("line = "+line);
}

//方法二  【打印结果为b=0   b=0】
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch;
while((ch=inputStream.read()) != -1){
bos.write(ch);
}
byte[] bt = bos.toByteArray();
bos.close();
for(byte b : bt){
System.out.print("b="+ b +"\t");
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
 //关闭流和端口
            try {
             System.out.println("关闭端口");
             if (br != null) {
         br.close();
         }
                if(serialPort != null){
                 serialPort.close();
                }
            }catch(Exception e){   
                System.out.println("关闭端口时异常出现:"+e.getMessage());
            }
}
}
}
使用方法一时异常信息如下:
java.io.IOException: Underlying input stream returned zero bytes
at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder$CharsetSD.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at com.main2.Test.serialEvent(Main.java:91)
at gnu.io.RXTXPort.sendEvent(RXTXPort.java:732)
at gnu.io.RXTXPort.eventLoop(Native Method)
at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1575)这段代码的功能是:通过串口向一块电路板发送一段命令,在发送命令前,设置RTS为关闭状态【如代码中】,发送以后,打开RTS【如代码中】,会收到返回值。发送命令是成功的,因为如果发送成功的话,会打开一个led灯。但是在读取返回值方面抛出了这个异常。
这个问题花了我整整一个月,也没有搞定,查了很多很多资料,试了很多种方法,都没有找到解决方案,google了这个异常,看到一些英文相关的论坛帖子,貌似这个是java的bug。
求各位大侠帮忙!时间还是比较紧的,搞不定的话,我自己都待不下去了之前本人发过类似的帖子:http://topic.csdn.net/u/20100611/20/8ceab9f5-68b1-4f6c-aec7-05280ae5f190.html

解决方案 »

  1.   

    当然,这个程序的最终目的是为了获得正确的返回值。即如果您知道如何能得到正确的返回值,可以直接贴上代码,而不管这个异常。我用了一个串口调试工具【同事给的,vb写的一个工具】,在发送命令后,会获得返回值,截图如下:PS:程序中的那个字节数组应该和这个图中的那个发送命令一样,不过没有关系,不影响问题,这个我可以保证。
      

  2.   

    曾经在scounix环境下用c语言和磁条读写器、芯片卡读写器、打印机等打过交道,一般来说都是厂商给来驱动程序包或者sample code,如果是sample code我们可以根据sample code编写。
    看情况你是先肯定电路板那里没问题咯?怎么排除电路板是没问题的呢?是用其他语言编写过样例程序通讯的么?如果是C语言,可以尝试拷贝C语言到java环境下。另外也可以考虑jni
      

  3.   

    很难理解你为什么用BufferedReader,而且还用br.readLine,这个又不是文本数据接口。看看BufferedReader的jdk说明
    Read text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines. 
      

  4.   

    serialEvent方法是消息响应接口链路中的吧?
    等接到消息了再去创建br呢?
    inputStream = sPort.getInputStream();
    br = new BufferedReader(new InputStreamReader(inputStream));这些调试过吗
      

  5.   

    证明电路板没问题的理由在1楼。用那个工具把命令发给这个电路板后,获得了返回值。1、我并不是简单的用BufferedReader,而是用了一个过渡的类InputStreamReader【将字节流转化为字符流】
    2、我在测试的时候并不会只用这一种读取方法,我试了很多很多种,其中的一种也在发帖的时候写上去了,就是“方法二”。
      

  6.   

    我在网上收了一下相交资料,有一个人提出了一种解决方案,你看懂这些可能就会解决这个问题了。 
    The problem is that, at the end of a line, the GPS receiver sends a line feed character (ascii code = 10) and/or a carriage return character (ascii code = 13). Then, you must test if the current character stocked in your "line" variable (while ((line = in.readLine()) != null) ) is 10 or 13. If YES, you must break your while function to avoid reading the rest of the line. It should solve your problem. 下面是相关代关键码 
    Java代码 
    BufferedReader inStream = new BufferedReader(new InputStreamReader(inputStream));   
      
    byte ch = 0;   
      
    char myChar;   
      
    int charVal;   
      
    try{   
      
    while((ch = (byte)inStream.read()) != -1){   
      
    if((ch == 13) || (ch == 10)){ //In ASCII code: 13 = Carriage return, 10 = line feed. When the GPS receiver sends those characters, the while loop must be broken to avoid an IOException   
      
    break;   
      
    }else{   
      
    myChar = (char)ch;   
      
    charVal = myChar;   
      
    //System.out.print("byte=" + ch +" myChar=" + myChar + " charVal=" + charVal + "\n");   
      
    System.out.print(myChar);   
      
    }   
      
    }  
      

  7.   

    http://topic.csdn.net/u/20100611/20/8ceab9f5-68b1-4f6c-aec7-05280ae5f190.html?65359
    上我的回答看看对你有没有帮助
      

  8.   

    呵呵,不好意思。刚才一打开发现是我自己的帖子,就没看。呵呵。这个题目已经做好了,代码如下:package com.main2;   
      
    import gnu.io.CommPortIdentifier;   
    import gnu.io.SerialPort;   
    import gnu.io.SerialPortEvent;   
    import gnu.io.SerialPortEventListener;   
      
    import java.io.ByteArrayOutputStream;   
    import java.io.InputStream;   
    import java.io.OutputStream;   
    import java.util.Enumeration;   
      
    public class Test extends Thread implements SerialPortEventListener {   
        static Enumeration portList;   
        static CommPortIdentifier portId;   
        static InputStream inputStream;   
        static OutputStream outputStream;   
        static SerialPort serialPort;   
        static int count = 0;   
           
        public static void main(String[] args) {   
            portList = CommPortIdentifier.getPortIdentifiers();   
            while (portList.hasMoreElements()) {   
                portId = (CommPortIdentifier) portList.nextElement();   
                if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {   
                    if (portId.getName().equals("COM3")) {   
                        Test test = new Test();   
                    }   
                }   
            }   
        }   
      
        public Test() {   
            try {   
                //打开通讯   
                serialPort = (SerialPort) portId.open("ReadCommApp", 2000);   
                serialPort.setRTS(false);//此步骤可以省略,猜测默认情况即是false   
               
                serialPort.setSerialPortParams(2400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);   
               
                byte[]  bt = new byte[]{(byte)0xaa,(byte)0x00,(byte)0xdd,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x55};   
               
                outputStream = serialPort.getOutputStream();   
                outputStream.write(bt);   
                outputStream.flush();   
                outputStream.close();   
                Thread.sleep(200); //50~~1400   
               
                serialPort.setRTS(true);   
                inputStream = serialPort.getInputStream();   
               
                serialPort.addEventListener(this);   
                serialPort.notifyOnDataAvailable(true);   
            } catch (Exception e) {   
                e.printStackTrace();   
            }   
        }   
      
        public void serialEvent(SerialPortEvent event) {   
            try{   
                if (event.getEventType() == event.DATA_AVAILABLE){   
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();   
                    int ch;   
                    while((ch=inputStream.read()) != -1){   
                        count++;   
                        if(count>2){   
                            bos.write(ch);   
                        }   
                           
                    }   
                    byte[] bt = bos.toByteArray();   
                    for(byte b : bt){   
                        System.out.print("b="+b+"\t");//b=-86  b=0  b=-35   b=3  b=0  b=0  b=85  b=85   
                    }   
                    bos.close();       
                }   
            }catch(Exception e){   
                e.printStackTrace();   
            }   
        }   

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/config_man/archive/2010/06/30/5705264.aspx
    我在博客里写的较为详细,大家如果不太明白的话,可以到我的博客里再看看。感谢各位网友的热心帮助!!!再次感谢!!!结贴!!!