如何拆分串口InputStream?实现单发送供双方法处理
解决串口InputStream单次读取供双方法处理的方案
完全可以实现,核心思路是先把串口输入流的所有数据一次性读取并缓存到内存中,再基于缓存的数据创建多个独立的输入流实例,分别传给你的两个处理方法,这样单次发送的数据就能被两个方法完整获取。
具体实现步骤
- 第一步:从串口InputStream读取所有数据到内存缓存(比如
ByteArrayOutputStream或byte数组) - 第二步:用缓存的数据创建多个
ByteArrayInputStream,分别交给处理String和二进制数据的方法 - 第三步:两个方法各自操作独立的输入流,互不干扰
修改后的代码示例
private static void readingBytesSN(SerialPort comPort) { comPort.addDataListener(new SerialPortDataListener() { @Override public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_AVAILABLE; } @Override public void serialEvent(SerialPortEvent serialPortEvent) { if (serialPortEvent.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) { return; } // 1. 先把串口数据全部读取到内存缓存 byte[] cachedData = null; try (InputStream in = comPort.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; int bytesRead; // 循环读取直到流结束或检测到协议结束标志 while ((bytesRead = in.read(buffer)) != -1) { baos.write(buffer, 0, bytesRead); // 根据你原代码的结束标志,判断是否终止读取 byte[] tempBytes = baos.toByteArray(); String tempStr = baos.toString(); if (tempStr.contains("\u001Bm\u001B3") || (tempBytes.length > 0 && tempBytes[tempBytes.length-1] == 109)) { break; } } cachedData = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); return; } // 2. 创建两个独立的输入流,分别给两个处理方法 try (ByteArrayInputStream stringInputStream = new ByteArrayInputStream(cachedData); ByteArrayInputStream binaryInputStream = new ByteArrayInputStream(cachedData)) { // 调用处理String数据的方法 processStringData(stringInputStream); // 调用处理二进制数据的方法 processBinaryData(binaryInputStream); } catch (IOException e) { e.printStackTrace(); } } }); } // 处理String数据的方法(适配你原逻辑) private static void processStringData(InputStream in) throws IOException { Scanner sc = new Scanner(in); List<String> lines = new ArrayList<>(); while (sc.hasNextLine()) { String line = sc.next(); lines.add(line); if (line.contains("\u001Bm\u001B3")) { break; } } // 这里添加你对String数据的后续处理逻辑 System.out.println("String数据处理完成"); } // 处理二进制数据的方法(复用你原有的SN处理逻辑) private static void processBinaryData(InputStream in) throws IOException { String startSn2 = "110000010011010001101100100011011000100011010000111000010001010"; String newLine2 = "01100000110110010001101100010001101000011100001000101"; String s1 = ""; int x; while (((x = in.read()) != 109) && x != -1) { s1 += String.format("%8s", Integer.toBinaryString(x & 0xFF)).replace(' ', '0'); } String[] snArray = s1.split(startSn2); for (int i = 1; i < snArray.length; i++) { // 原有的图片生成与OCR逻辑 BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); Graphics2D g2d = img.createGraphics(); Font font = new Font("Arial", Font.PLAIN, 2); g2d.setFont(font); int height = g2d.getFontMetrics().getHeight(); g2d.dispose(); img = new BufferedImage(384, 40, BufferedImage.TYPE_INT_RGB); g2d = img.createGraphics(); g2d.setFont(font); g2d.setColor(Color.WHITE); int fontSize = 1; for (String line : snArray[i].split(newLine2)) { g2d.drawString(line, 0, height); height += fontSize; } try { ImageIO.write(img, "png", new File("images\\Text" + i + ".png")); } catch (IOException ex) { ex.printStackTrace(); } g2d.dispose(); String result = null; try { result = SerialOcr("images\\Text" + i + ".png"); } catch (TesseractException e) { e.printStackTrace(); } System.out.println(result); } }
关键说明
- 缓存数据时必须根据串口协议设置结束判断:串口输入流不会主动关闭,所以要通过你业务中的结束标志(比如原代码里的109或
\u001Bm\u001B3)终止读取,避免无限等待。 ByteArrayInputStream是基于内存数组的输入流,每个实例独立维护读取指针,两个方法的读取操作完全互不干扰。- 原代码中
Scanner和in.read()共享同一个流的指针,会导致第二个方法无法读取完整数据,缓存后彻底解决了这个问题。
内容的提问来源于stack exchange,提问作者Danilo Djurovic
相关产品推荐
相关产品推荐

