You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拆分串口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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:05:14