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

Android蓝牙缓冲区字符串转int报NumberFormatException如何解决?

Android蓝牙串口字符串转int类型NumberFormatException异常解决方案

问题根因

错误日志显示读取到的串口字符串末尾带有换行符\n等不可见空白字符,不符合Integer.parseInt()要求的纯数字格式,同时原代码没有做异常兜底和粘包分包处理,最终导致崩溃。

分步解决方法

1. 字符串清洗

对读取到的字符串先去除首尾所有空白字符,再校验是否为纯数字后再转换,同时加异常捕获避免崩溃。
核心代码:

// 清洗字符串,去除换行、空格、回车等首尾空白
String cleanStr = strInput.trim();
int data = 0;
try {
    // 校验是否为纯数字
    if (cleanStr.matches("\\d+")) {
        data = Integer.parseInt(cleanStr);
    } else {
        Log.d("BluetoothData", "收到非数字内容:" + cleanStr);
        return;
    }
} catch (NumberFormatException e) {
    e.printStackTrace();
    Log.e("BluetoothData", "数字转换失败,原始内容:" + strInput);
    return;
}

2. 解决串口粘包分包问题

蓝牙串口通信默认是流传输,没有数据包边界,会出现一次读取多条数据或者单条数据分多次读取的情况,需要新增全局缓冲区,按换行符拆分完整数据包再处理。
在ReadInput类中新增缓冲区成员:

private StringBuilder dataBuffer = new StringBuilder();

读取数据后先拼入缓冲区再拆分处理:

// 新读取的内容拼入缓冲区
dataBuffer.append(strInput);
// 按换行符拆分完整数据包
int lineIndex;
while ((lineIndex = dataBuffer.indexOf("\n")) != -1) {
    // 取出一条完整消息
    String fullMessage = dataBuffer.substring(0, lineIndex);
    // 移除已处理的消息
    dataBuffer.delete(0, lineIndex + 1);
    // 此处对fullMessage做清洗转换逻辑即可
}

3. 修正原代码线程安全问题

原代码在子线程中更新highest、lowest等TextView控件,属于子线程操作UI的错误逻辑,会触发异常,修改为阈值直接从SharedPreferences读取即可,不要在子线程操作UI。

完整核心修改代码

// ReadInput类的run方法完整修改
@Override
public void run() {
    InputStream inputStream;
    // 全局数据缓冲区,解决粘包分包
    final StringBuilder dataBuffer = new StringBuilder();
    try {
        inputStream = mBTSocket.getInputStream();
        while (!bStop) {
            byte[] buffer = new byte[256];
            if (inputStream.available() > 0) {
                inputStream.read(buffer);
                int i;
                for (i = 0; i < buffer.length && buffer[i] != 0; i++) {
                }
                final String strInput = new String(buffer, 0, i);

                if (chkReceiveText.isChecked()) {
                    mTxtReceive.post(new Runnable() {
                        @Override
                        public void run() {
                            mTxtReceive.append(strInput);
                            // 拼入缓冲区
                            dataBuffer.append(strInput);
                            int lineIndex;
                            // 拆分所有完整数据包
                            while ((lineIndex = dataBuffer.indexOf("\n")) != -1) {
                                String fullMsg = dataBuffer.substring(0, lineIndex);
                                dataBuffer.delete(0, lineIndex + 1);
                                // 清洗转换
                                String cleanStr = fullMsg.trim();
                                int data = 0;
                                boolean dataValid = false;
                                try {
                                    if (cleanStr.matches("\\d+")) {
                                        data = Integer.parseInt(cleanStr);
                                        dataValid = true;
                                    }
                                } catch (NumberFormatException e) {
                                    e.printStackTrace();
                                }
                                // 阈值比较逻辑
                                if (dataValid) {
                                    SharedPreferences sp = getSharedPreferences(mypreference, Context.MODE_PRIVATE);
                                    String hiStr = sp.getString(Highest, "0");
                                    int hi = Integer.parseInt(hiStr);
                                    if (data < hi) {
                                        Log.d(TAG, "succes");
                                    }
                                }
                            }
                            // 原有日志滚动逻辑
                            int txtLength = mTxtReceive.getEditableText().length();
                            if(txtLength > mMaxChars){
                                mTxtReceive.getEditableText().delete(0, txtLength - mMaxChars);
                            }
                            if (chkScroll.isChecked()) {
                                scrollView.fullScroll(View.FOCUS_DOWN);
                            }
                        }
                    });
                }
            }
            Thread.sleep(500);
        }
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }
}

内容的提问来源于stack exchange,提问作者Whiliams Thunardy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 05:45:06