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
相关产品推荐
相关产品推荐

