Fifo缓冲区,它允许空元素

问题描述:

我有一个设备,通过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事件 * 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

您可以用您的自定义字节类包裹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

一个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