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

Flutter蓝牙设备扫码字符串异常:无法作为Hive过滤条件问题

蓝牙扫码数据转字符串后Hive过滤失效的排查与解决

问题场景

开发Flutter蓝牙扫码应用时,通过特征值流读取扫码数据并转换为字符串,代码实现如下:

late StreamSubscription<List<int>> _lastValueSubscription;
_lastValueSubscription = characteristic.lastValueStream.listen((value) {
  _value = value;
  String skuCode = String.fromCharCodes(_value);
});

转换得到的skuCode打印显示为正常字符串,但IDE hover时无类型标识,且作为Hive过滤条件时无法返回结果;手动输入相同字符串则能正常匹配。

核心原因

问题根源在于蓝牙设备返回的字节流中包含不可见的控制字符(如换行\n、回车\r、空字符\0等),这些字符打印时无法察觉,但会导致转换后的字符串与手动输入的纯字符串实际不相等。此外,编码不匹配也可能引发类似问题。

解决方案

1. 清理字符串中的隐形控制字符

通过trim()去除首尾空白,再用正则替换掉所有ASCII控制字符:

_lastValueSubscription = characteristic.lastValueStream.listen((value) {
  _value = value;
  String rawCode = String.fromCharCodes(_value);
  // 清理所有不可见控制字符和首尾空白
  String skuCode = rawCode.trim().replaceAll(RegExp(r'[\x00-\x1F\x7F]'), '');
});

2. 验证字符串的实际内容

打印字符串长度和每个字符的Unicode码点,对比手动输入的字符串,确认是否存在隐形字符:

print('扫码字符串长度: ${skuCode.length}');
skuCode.runes.forEach((rune) => print('字符码点: $rune'));

// 对比手动输入的字符串
String manualSku = '测试扫码码';
print('手动输入字符串长度: ${manualSku.length}');
manualSku.runes.forEach((rune) => print('字符码点: $rune'));

3. 指定正确的编码格式

如果蓝牙设备使用ASCII或UTF-8编码,显式指定解码方式避免默认编码导致的问题:

// 使用UTF-8解码(推荐,兼容更多场景)
import 'dart:convert';
String skuCode = utf8.decode(_value).trim();

// 若设备明确使用ASCII编码
String skuCode = ascii.decode(_value).trim();

4. 优化Hive过滤逻辑

确保过滤前先清理字符串,避免隐形字符干扰匹配:

final cleanedSku = skuCode.trim().replaceAll(RegExp(r'[\x00-\x1F\x7F]'), '');
final filteredItems = Hive.box('skuBox').values
    .where((item) => item.skuCode == cleanedSku)
    .toList();

内容的提问来源于stack exchange,提问作者Ramiz Girach

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:22:13