如何从BufferedReader生成带换行字符串并解析串口GPS数据
解决串口GPS数据读取格式问题,实现可解析的完整行数据获取
问题根源分析
你原来的代码有几个关键问题导致输出格式异常:
- 每次仅读取1个字节,然后用
ByteArrayInputStream和BufferedReader去读行——这完全是多此一举,因为单个字节不可能构成完整行,readLine()根本无法触发换行逻辑,而且你最后错误打印了BufferedReader对象本身(System.out.println(in);),不是读取到的内容。 - 没有对读取到的字节进行缓存拼接,导致每个字符被单独处理,出现了字符间带空格的错误输出。
而serialPort.readString(event.getEventValue())能正常工作,是因为event.getEventValue()返回的是当前串口缓冲区中可用的字节总数,一次性读取所有可用数据,自然能得到连续的字符片段,输出就是正常的格式。
正确实现方案:缓存拼接+按行分割
我们需要维护一个全局的字符串缓存,累积读取到的所有字符,每次读取后检查是否包含换行符(\r\n,对应串口数据的回车+换行结尾),分割出完整的行进行解析,剩余的不完整部分留在缓存中等待下一次数据。
修改后的SerialPortReader代码如下:
static class SerialPortReader implements SerialPortEventListener { // 全局缓存,用于累积未完成的行数据 private final StringBuilder dataBuffer = new StringBuilder(); public void serialEvent(SerialPortEvent event) { if (event.getEventType() != SerialPortEvent.DATA_AVAILABLE) { return; // 只处理有数据可用的事件 } try { // 一次性读取所有可用数据,对应event.getEventValue()的逻辑 byte[] readBytes = serialPort.readBytes(event.getEventValue()); if (readBytes == null || readBytes.length == 0) { return; } // 将字节转换为字符串,追加到缓存 String newData = new String(readBytes, StandardCharsets.UTF_8); dataBuffer.append(newData); // 处理缓存中的完整行 processCompleteLines(); } catch (SerialPortException | IOException ex) { ex.printStackTrace(); // 不要吞掉异常,方便调试 } } private void processCompleteLines() { String bufferContent = dataBuffer.toString(); int lineEndIndex; // 循环查找所有完整的行(以\r\n结尾) while ((lineEndIndex = bufferContent.indexOf("\r\n")) != -1) { // 提取完整行 String completeLine = bufferContent.substring(0, lineEndIndex); // 这里就是你可以解析的完整GPS数据行 System.out.println("解析用完整行:" + completeLine); // 示例:按逗号分割解析 String[] gpsFields = completeLine.split(","); // 这里可以添加你的解析逻辑,比如处理$GPGGA、$GPGSA等语句 // 更新缓存,保留未处理的剩余部分 bufferContent = bufferContent.substring(lineEndIndex + 2); // +2跳过\r\n dataBuffer.setLength(0); dataBuffer.append(bufferContent); } } }
关键说明
- 缓存机制:用
StringBuilder作为缓存,避免频繁字符串拼接的性能损耗。 - 一次性读取:通过
event.getEventValue()获取可用字节数,一次性读取所有数据,和你测试有效的readString逻辑一致。 - 按行分割:每次读取后检查缓存中的
\r\n,确保只处理完整的GPS语句,不解析不完整的片段。 - 异常处理:去掉了空的catch块,添加
ex.printStackTrace()方便调试问题。
这样实现后,你就能得到和System.out.print(wtf)一样的连续字符串,并且可以直接按逗号分割解析每一行完整的GPS数据了。
内容的提问来源于stack exchange,提问作者javanewbie14
相关产品推荐
相关产品推荐

