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

为何BufferedReader与Scanner无法识别串口数据中的换行符?

串口读取中BufferedReader无法识别\r作为行分隔符的原因

问题背景

我用jSerialComm开发了读取外部测试仪器串口数据的程序,数据按行分隔。最初用BufferedReader的readLine()逐行读取,但调用后会一直阻塞直到超时;换成Scanner的nextLine()也遇到同样问题。

排查后发现仪器以ASCII 13(回车符\r)作为行分隔符,虽然BufferedReader的JavaDoc说明它能识别\r作为行终止符,但实际就是不生效。后来自行编写了ScaleReader类,能正确识别\n和\r,调用其readLine()可正常获取数据,想知道BufferedReader失效的原因。

相关代码

原BufferedReader实现

SerialPort port = SerialPort.getCommPort("COM4");
port.openPort();
port.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 10000, 0);
BufferedReader reader = new BufferedReader(new InputStreamReader(port.getInputStream()));
while(true) {
    // 该行一直阻塞
    System.out.println(reader.readLine());
}

原始字节读取代码

int byteRead;
InputStream stream = port.getInputStream();
while ((byteRead = stream.read()) != -1) {
    System.out.write(byteRead);
    System.out.print(byteRead);
}

自定义ScaleReader类

public class ScaleReader {

    private InputStream scaleInputStream;

    public ScaleReader(InputStream scaleInputStream) {
        this.scaleInputStream = scaleInputStream;
    }

    public String readLine() throws IOException {
        StringBuilder builder = new StringBuilder();

        int charByte = scaleInputStream.read();
        while (charByte != -1 && charByte == 13 || charByte == 10)
            charByte = scaleInputStream.read();

        if (charByte == -1)
            return null;

        builder.append((char) charByte);
        
        while (true) {
            charByte = scaleInputStream.read();
            if (charByte == -1 || charByte == 13 || charByte == 10)
                break;

            builder.append((char) charByte);
        }

        return builder.length() == 0 ? null : builder.toString();
    }

}

原因分析

BufferedReader的readLine()确实会把\r视为行终止符,但它的处理逻辑存在特殊判断:

  • 当读到\r时,会继续读取下一个字节,判断是否是\n:
    • 如果是\n,就将这两个字符作为行终止符,返回之前的内容;
    • 如果不是\n(比如串口数据流到\r就结束,没有后续字节),它会持续阻塞等待,直到有新字节输入或者触发读取超时。

而你的自定义ScaleReader类读到\r就直接终止读取并返回内容,不会等待后续字节,因此能正常获取单条数据。串口场景下仪器发送完\r后不会再发送额外字节,BufferedReader的等待逻辑就会导致你遇到的阻塞问题。

内容的提问来源于stack exchange,提问作者Cardinal System

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 10:01:46