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)
您可以用您的自定义字节类包裹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
标志
这是不必要的。将'0x00'表示为'Byte'没有问题。它在Java意义上不是'null'。 – 2015-03-25 10:17:03
是的,无论如何Lawrey的答案似乎更有效率。 – giorashc 2015-03-25 10:20:09
我按照你的说法编写了一个自定义字节类,但是同样的,我在线程“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
,并在另一个线程就可以处理此字节。
此方法不会在每个字节的基础上创建任何垃圾。
如果使用Byte.valueOf(byte)获得Byte对象,则不会生成垃圾。 Byte类为所有256个可能的字节值缓存Byte对象。 – 2015-03-25 10:32:43
如何以最佳方式解析字节?消息格式为stx | len |消息| etx | crc – 2015-03-25 10:40:05
@GligorShijakovski我会尝试逐步读取数据。 – 2015-03-25 13:10:01
我不知道我明白,你不能添加'null'到'queue'元素? – fxm 2015-03-25 10:04:22
我添加和我检查队列的大小是2,但是当我轮询的元素我在线程“线程1”中得到异常java.lang.NullPointerException – 2015-03-25 10:06:30
@GligorShijakovski:这是因为你的'stx'变量的类型是'byte'而不是'Byte',所以它是自动拆箱。 (话说回来,目前还不清楚为什么你不只是保持现有形式的字节0 ......) – 2015-03-25 10:06:55