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

Java读取称重机串口数据乱码问题求助(jSerialComm、Java 8)

解决Java+jSerialComm读取称重机串口乱码问题

嘿,我来帮你搞定这个串口读取乱码的问题!结合你的场景和代码来看,大概率是串口参数不匹配或者字符编码选错了,咱们一步步来排查:

1. 先确认串口核心参数是否完全匹配

串口通信的波特率、数据位、停止位、奇偶校验这几个参数,必须和称重机的配置完全一致,不然读取到的二进制数据本身就是错乱的,再怎么转编码都会出现乱码。

你可以通过jSerialComm的API设置这些参数,示例代码如下(记得替换成称重机手册上的实际参数):

thisPort.setBaudRate(9600); // 常见波特率有9600、19200等
thisPort.setNumDataBits(8); // 大多是8位数据位
thisPort.setNumStopBits(1); // 1位停止位
thisPort.setParity(SerialPort.NO_PARITY); // 无校验

2. 排查字符编码问题

你当前用的UTF-8编码,很多工业设备(比如称重机)其实用的是ASCII、GBK或者ISO-8859-1这类编码。尤其是ASCII,是工业串口设备最常用的编码。

建议你先直接读取原始字节,再尝试用不同编码解析,这样能直观看到问题所在:

InputStream is = thisPort.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while (true) {
    try {
        if ((bytesRead = is.read(buffer)) > 0) {
            // 打印原始字节,对比正确数据的字节值(比如"N + 60 kg"的ASCII字节是[78,32,43,32,54,48,32,107,103])
            System.out.println("原始字节: " + Arrays.toString(Arrays.copyOf(buffer, bytesRead)));
            // 尝试不同编码解析
            String asciiStr = new String(buffer, 0, bytesRead, "ASCII");
            String gbkStr = new String(buffer, 0, bytesRead, "GBK");
            String isoStr = new String(buffer, 0, bytesRead, "ISO-8859-1");
            System.out.println("ASCII解析结果: " + asciiStr);
            System.out.println("GBK解析结果: " + gbkStr);
            System.out.println("ISO-8859-1解析结果: " + isoStr);
        }
    } catch (Exception e) {
        System.err.println(e.getMessage());
        if (e.getMessage().contains("shutdown or disconnected")) break;
    }
}

从输出里找到能正确显示N + X kg的编码,之后就用这个编码来解析数据。

3. 避免依赖readLine()读取数据

readLine()是通过换行符(\n或\r\n)来判断一行结束的,但很多工业设备发送数据时可能不带换行符,或者用\r作为结束标志,这会导致readLine()一直等待,或者读取到不完整的片段,进而出现乱码。

更可靠的方式是读取字节数组,自己判断完整数据包的结束标志(比如你的称重机数据以 kg结尾),示例逻辑如下:

StringBuilder dataBuilder = new StringBuilder();
// 读取字节片段后拼接
dataBuilder.append(chunk);
// 检查是否是完整数据包
if (dataBuilder.toString().endsWith(" kg")) {
    String fullData = dataBuilder.toString();
    System.out.println("完整数据: " + fullData);
    // 这里可以提取重量数值
    dataBuilder.setLength(0); // 重置构建器,准备下一个数据包
}

4. 清空串口缓冲区

打开串口后,缓冲区可能残留之前的旧数据,导致第一次读取出现乱码。你可以在打开串口后添加这行代码清空读缓冲区:

thisPort.clearPortBuffers(SerialPort.BUFFER_READ);

整合后的完整示例代码

import com.fazecast.jSerialComm.SerialPort;
import java.io.InputStream;
import java.util.Arrays;

public class ScaleSerialReader {
    public static void main(String[] args) {
        // 替换成你的串口名,比如Windows的COM3,Linux的/dev/ttyUSB0
        SerialPort thisPort = SerialPort.getCommPort("COM3");
        
        // 设置串口参数,必须和称重机一致
        thisPort.setBaudRate(9600);
        thisPort.setNumDataBits(8);
        thisPort.setNumStopBits(1);
        thisPort.setParity(SerialPort.NO_PARITY);
        
        if (!thisPort.openPort()) {
            System.err.println("无法打开串口,请检查串口是否被占用");
            return;
        }
        
        // 清空读缓冲区,避免旧数据干扰
        thisPort.clearPortBuffers(SerialPort.BUFFER_READ);
        
        InputStream is = thisPort.getInputStream();
        byte[] buffer = new byte[100];
        int bytesRead;
        StringBuilder dataBuilder = new StringBuilder();
        
        while (true) {
            try {
                if ((bytesRead = is.read(buffer)) > 0) {
                    // 用ASCII解析(如果测试后是其他编码,替换成对应编码)
                    String chunk = new String(buffer, 0, bytesRead, "ASCII").trim();
                    dataBuilder.append(chunk);
                    
                    // 检查是否收到完整的数据包(以" kg"结尾)
                    String currentData = dataBuilder.toString();
                    if (currentData.endsWith(" kg")) {
                        System.out.println("读取到完整数据: " + currentData);
                        
                        // 提取重量数值
                        if (currentData.startsWith("N + ")) {
                            String weightStr = currentData.substring(4, currentData.indexOf(" kg"));
                            try {
                                double weight = Double.parseDouble(weightStr);
                                System.out.println("当前重量: " + weight + " kg");
                            } catch (NumberFormatException e) {
                                System.err.println("解析重量失败: " + e.getMessage());
                            }
                        }
                        
                        // 重置构建器,准备接收下一个数据包
                        dataBuilder.setLength(0);
                    }
                }
            } catch (Exception e) {
                System.err.println("读取异常: " + e.getMessage());
                if (e.getMessage().contains("shutdown or disconnected")) {
                    System.out.println("串口已断开,退出读取");
                    break;
                }
            }
        }
        
        // 关闭串口
        thisPort.closePort();
    }
}

按照上面的步骤排查,应该就能解决乱码问题啦!

内容的提问来源于stack exchange,提问作者Samuel Munyili

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:24:15