2015-03-25 101 views
0

我有一個設備,通過rs232與程序交流。設備發送消息和程序讀取一個字節的字節,並放入緩衝區,所以另一個線程解析緩衝區。 問題是,在消息中,我將有一個0x00字節{用於fifo緩衝區的空元素},所以我不能在fifo中輸入該元素。如何解決該問題。 我用Fifo緩衝區,它允許空元素

BlockingQueue<Byte> queue = new ArrayBlockingQueue<>(1000); 

對於在FIFO進入字節:

public void serialEvent(jssc.SerialPortEvent event) { 
    if (event.isRXCHAR()) {//If data is available 
    try { 
     buffer = serialPort.readBytes(); 
     System.out.println(bytesToHex(buffer) + " event"); 
     for (int i = 0; i < buffer.length; i++) { 
     queue.add(buffer[i]); 
     } 
    } catch (SerialPortException ex) { 
     System.out.println(ex); 
    } 

而對於投票的元素

byte stx = queue.poll(); 

如何進入null元素,因爲消息將有一個空字節?

用於解析(線程解析)的代碼:

public void run() { 
      while (true) { 
       while (!queue.isEmpty()) { 
        System.out.println(queue.size() + " 1 proverka"); 
        sb = new StringBuilder(); 
        byte stx = queue.poll(); 
        System.out.println(byteToHex(stx) + " parser"); 
        if (stx == 0x02) { 
         sb.append(String.format("%02X ", stx)); 
         System.out.println(queue.size() + " 2 proverka"); 
         for (int i = 0; i < 3; i++) { 
          System.out.println(queue.size() + " 3 proverka " + i + " krug"); 
          len[i] = queue.poll(); 
          System.out.println(byteToHex(len[i]) + " parser"); 

輸出:

02事件 0000事件 01事件 4 1 proverka 77事件 2解析器 03事件 75事件 6 2 proverka 6 3 proverka 0 krug 線程「線程-1」中的異常java.lang.NullPointerException 在es.moduli.ingenico_card_reader.Ingenico_Card_Reader $ SerialParser.run(Ingenico_Card_Reader.java:127)

編輯與我的自定義字節級

/* 
* To change this license header, choose License Headers in Project Properties. 
* To change this template file, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package es.moduli.ingenico_card_reader; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.TimeUnit; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import jssc.SerialPort; 
import jssc.SerialPortEventListener; 
import jssc.SerialPortException; 

/** 
* 
* @author GiGo 
*/ 
public class Ingenico_Card_Reader { 

    static SerialPort serialPort; 
    static BlockingQueue<CustomByte> queue = new ArrayBlockingQueue<>(1000); 
    final protected static char[] hexArray = "ABCDEF".toCharArray(); 

    public void open() { 
     serialPort = new SerialPort("COM4"); 
     try { 
      serialPort.openPort();//Open port 
      serialPort.setParams(9600, 8, 1, 0);//Set params 
      int mask = SerialPort.MASK_RXCHAR;//Prepare mask 
      serialPort.setEventsMask(mask);//Set mask 
      serialPort.addEventListener(new SerialPortEvent());//Add SerialPortEventListener 
     } catch (SerialPortException ex) { 
      System.out.println(ex); 
     } 

     SerialParser parser = new SerialParser(); 
     parser.start(); 
    } 

    public static String bytesToHex(byte[] bytes) { 
     char[] hexChars = new char[bytes.length * 2]; 
     for (int j = 0; j < bytes.length; j++) { 
      int v = bytes[j] & 0xFF; 
      hexChars[j * 2] = hexArray[v >>> 4]; 
      hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
     } 
     return new String(hexChars); 
    } 

    public static String byteToHex(byte b) { 
     int i = b & 0xFF; 
     return Integer.toHexString(i); 
    } 

    public static int byteToIntBE(byte[] b) { 
     ByteBuffer bb = ByteBuffer.wrap(b); 
     bb.order(ByteOrder.BIG_ENDIAN); 
     int result = bb.getInt(); 
     return result; 
    } 

    public static void sleep(long i) { 
     try { 
      Thread.sleep(i); 
     } catch (Exception e) { 
     } 
    } 

    public static String hexString(byte[] b) { 
     StringBuilder d = new StringBuilder(b.length * 2); 
     for (int i = 0; i < b.length; i++) { 
      char hi = Character.forDigit(b[i] >> 4 & 0xF, 16); 
      char lo = Character.forDigit(b[i] & 0xF, 16); 
      d.append(Character.toUpperCase(hi)); 
      d.append(Character.toUpperCase(lo)); 
     } 
     return d.toString(); 
    } 

    public static class SerialPortEvent implements SerialPortEventListener { 

     byte buffer[]; 

     @Override 
     public void serialEvent(jssc.SerialPortEvent event) { 
      if (event.isRXCHAR()) {//If data is available 
       //if (event.getEventValue() == 1) {//Check bytes count in the input buffer 
       //Read data, if 1 byte available 
       try { 
        buffer = serialPort.readBytes(); 
        System.out.println(bytesToHex(buffer) + " event"); 
        for (int i = 0; i < buffer.length; i++) { 
         queue.add(new CustomByte(buffer[i], true)); 
        } 
       } catch (SerialPortException ex) { 
        System.out.println(ex); 
       } 
      } 
      // } 

     } 
    } 

    public static class SerialParser extends Thread { 

     StringBuilder sb = new StringBuilder(); 
     Byte len[]; 
     int len_mess = 0; 
     Byte mess[]; 

     @Override 
     public void run() { 
      while (true) { 
       while (!queue.isEmpty()) { 
        System.out.println(queue.size() + " 1 proverka"); 
        sb = new StringBuilder(); 
        byte stx = queue.poll().getBufferByte(); 
        System.out.println(byteToHex(stx) + " parser"); 
        if (stx == 0x02) { 
         sb.append(String.format("%02X ", stx)); 
         System.out.println(queue.size() + " 2 proverka"); 
         for (int i = 0; i < 3; i++) { 
          System.out.println(queue.size() + " 3 proverka " + i + " krug"); 
          len[i] = queue.poll().getBufferByte(); 
          System.out.println(byteToHex(len[i]) + " parser"); 
          //sb.append(String.format("%02X ", len[i])); 
         } 
         len_mess = (256 * 256 * len[0]) + (256 * len[1]) + (len[2]); 
         for (int i = 0; i < len_mess; i++) { 
          mess[i] = queue.poll().getBufferByte(); 
          System.out.println(byteToHex(mess[i]) + "parser"); 
          sb.append(String.format("%02X ", mess[i])); 
          try { 
           Thread.sleep(50); 
          } catch (InterruptedException ex) { 
           System.out.println(ex.getMessage()); 
          } 
         } 
         byte etx = queue.poll().getBufferByte(); 
         System.out.println(byteToHex(etx) + "parser"); 
         if (etx == 0x03) { 
          sb.append(String.format("%02X ", etx)); 
          System.out.println(sb.toString()); 
         } else { 
          System.out.println("NOT ETX"); 
         } 
        } else { 
         System.out.println("NOT STX"); 
        } 
        System.out.println(sb.toString()); 
       } 
      } 
     } 

    } 

} 

同樣的錯誤

02事件 0000017703事件 6 1 proverka 2 parser 75 event 6 2 proverka 6 3 proverka 0 krug 線程「Thread-1」中的異常java.lang.NullP ointerException 在es.moduli.ingenico_card_reader.Ingenico_Card_Reader $ SerialParser.run(Ingenico_Card_Reader.java:129)

+1

我不知道我明白,你不能添加'null'到'queue'元素? – fxm 2015-03-25 10:04:22

+0

我添加和我檢查隊列的大小是2,但是當我輪詢的元素我在線程「線程1」中得到異常java.lang.NullPointerException – 2015-03-25 10:06:30

+1

@GligorShijakovski:這是因爲你的'stx'變量的類型是'byte'而不是'Byte',所以它是自動拆箱。 (話說回來,目前還不清楚爲什麼你不只是保持現有形式的字節0 ......) – 2015-03-25 10:06:55

回答

0

您可以用您的自定義字節類包裹Byte類:

public class CustomByte { 
    private Byte bufferByte; 
    private boolean isNull; 

    // Add constructor, getters/setters as required 
} 

,並更改隊列類型使用這種類型。 然後,當你遇到一個null字節,僅在與標誌添加CustomByte對象:

queue.add(new CustomByte(buffer[i], true)) 

那麼當輪詢CustomByte對象,你可以查詢isNull標誌

+0

這是不必要的。將'0x00'表示爲'Byte'沒有問題。它在Java意義上不是'null'。 – 2015-03-25 10:17:03

+0

是的,無論如何Lawrey的答案似乎更有效率。 – giorashc 2015-03-25 10:20:09

+0

我按照你的說法編寫了一個自定義字節類,但是同樣的,我在線程「Thread-1」中得到了一個異常java.lang.NullPointerException – 2015-03-25 11:24:33

3

一個BlockingQueue<Byte>可以有(byte) 0x00值但它是非常處理字節流的低效方式。這將爲每個發送的實際字節創建大約16個字節的垃圾。

另一種方法是使用專爲這類任務設計的管道流。

PipedOutputStream out = new PipedOutputStream(); 
PipedInputStream in = new PipedInputStream(out); 

在線程從RS232閱讀,您可以通過從in讀寫你讀的out,並在另一個線程就可以處理此字節。

此方法不會在每個字節的基礎上創建任何垃圾。

+0

如果使用Byte.valueOf(byte)獲得Byte對象,則不會生成垃圾。 Byte類爲所有256個可能的字節值緩存Byte對象。 – 2015-03-25 10:32:43

+0

如何以最佳方式解析字節?消息格式爲stx | len |消息| etx | crc – 2015-03-25 10:40:05

+0

@GligorShijakovski我會嘗試逐步讀取數據。 – 2015-03-25 13:10:01